Questão:
Detectar a localização da fonte de luz usando vários fotoresistores
jackgu1988
2017-04-02 05:25:37 UTC
view on stackexchange narkive permalink

Ainda não sou um especialista, então perdoe qualquer terminologia possivelmente errada que eu possa ter usado.

Estou planejando colocar 6 sensores de luz a 1 metro (ou talvez mais) de distância um do outro. , assim (desculpe pelo esquema ruim, não sou um especialista, mas espero que faça sentido):

schematic

simular este circuito - Esquemático criado usando CircuitLab

Vou colocá-los em uma sala relativamente escura. Meu objetivo é quando eu aponto um flash para eles para ser capaz de dizer qual sensor está medindo os valores mais altos (de onde a luz está vindo) e por quanto tempo (em milissegundos).

Eu sei fazer as conexões e medir os valores. Minhas perguntas são duas:

  1. Qual é a maneira mais eficiente de detectar qual dos 4 sensores está registrando os valores mais altos? Estou assumindo que devo comparar os valores que eles estão registrando. No entanto, acho que se em cada loop eu classificar os valores capturados, o processo pode se tornar pesado. Acho que poderia minimizar as comparações, pois, por exemplo, se o valor de LDR1 for maior que LDR2 e LDR3, posso assumir que a fonte de luz não pode estar apontando para LDR6, por exemplo. No entanto, estou pensando que talvez possa haver uma maneira ainda mais eficiente de detectar isso (não necessariamente em software).

  2. Já que a sala não ficará completamente escura, o analógico os pinos registram alguns valores mesmo quando não estou apontando a luz do flash em sua direção. Existe uma maneira de filtrar isso? Encontrei calibração ( https://www.arduino.cc/en/tutorial/calibration), mas não tenho certeza se esta é a solução ideal. Leve em consideração que a fonte de luz pode não ser muito forte (mas sua luz com certeza será mais brilhante do que a luz da sala).

Dois respostas:
James Waldby - jwpat7
2017-04-02 10:53:11 UTC
view on stackexchange narkive permalink

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); }}  
Isso provavelmente vai resolver! Eu realmente gosto da segunda solução. No entanto, para calibrá-lo, o método que postei na minha pergunta provavelmente funcionará? Preciso medir por quanto tempo a luz do flash ficou acesa (em milissegundos), então acho que vou precisar de alguma calibração ou de um filtro passa-alta.
@jackgu1988, ver editar - embora eu ache que não resolvi o ms em, mas em vez disso fração do tempo nos últimos 0,8 segundos (com constantes mostradas)
Provavelmente vai resolver! Muito obrigado. No momento, estou esperando que mais alguns sensores sejam entregues. Vou relatar quando eu testar.
cjs
2017-04-02 06:36:08 UTC
view on stackexchange narkive permalink

Há apenas um ADC (conversor analógico para digital) no ATmega328P; os pinos de entrada analógica são multiplexados para que você escolha qual pino específico deseja amostrar. (Consulte a Seção 28 da folha de dados para obter detalhes.)

Tirar uma amostra leva tempo; quanto tempo depende de como você faz isso. A função analogRead () está documentada para levar cerca de 100 microssegundos. Ler seus seis sensores vai, portanto, levar pelo menos 600 microssegundos.

A amostra retornada é um número inteiro de 10 bits e se encaixa facilmente em dois bytes, ou mesmo um byte se você deixar cair os dois bits mais baixos ( o que é razoável para alguns aplicativos, e provavelmente o seu, porque, de qualquer forma, eles são mais erros de amostra do que dados). Quer você faça isso ou não, no entanto, você fica com uma quantidade muito pequena de dados para classificar de um conjunto de leituras: apenas seis valores.

O Arduino executa o ATmega328P a 16 MHz e muito as instruções são executadas em um único clock, fornecendo um desempenho de aproximadamente 16 instruções por microssegundo.

Poderíamos calcular, com base no tipo de tipo que você usa, o número de comparações e trocas que você provavelmente fará no casos médios e piores, mas não faz sentido em um conjunto de dados tão pequeno porque o tempo total que sua rotina leva quase certamente será dominado por outras despesas gerais. Então, vou apenas dizer que a classificação será algo na ordem de cem ciclos de clock.

Isso significa que sua classificação adicionaria cerca de 6 ou 7 microssegundos ao seu tempo total de leitura de 600 microssegundos. ' chegamos até agora, ou 1%; você não precisa se preocupar com isso.

Na verdade, você vai passar muito mais tempo fazendo outros tipos de processamento. Mas é uma CPU muito rápida, como vimos acima, então há uma boa chance se você tomar cuidado de que seu loop ainda seja dominado pelo tempo de amostragem do ADC para cada um dos sensores.

Minha sugestão é seguir em frente e escrever a coisa, mas registrar os tempos reais em seu loop para a amostragem e o processamento. Depois de brincar um pouco com isso, você terá uma ideia melhor dos custos específicos de cada um para seu aplicativo específico e então poderá se preocupar se precisa ou não de otimização. Suspeito que não.

Com relação à "filtragem", isso será parte integrante do seu algoritmo de processamento porque os valores de "luz ambiente" podem ser muito diferentes de vez em quando, dependendo da corrente iluminação na sala. Não acho que você queira "filtrar" nada, mas sim comparar os valores de todos os fotorresistores; à primeira vista, valores semelhantes de todos eles significariam que não há lanterna e alguns dando-lhe valores significativamente mais altos indicariam que há uma. Mas meu segundo palpite é que a) você vai querer seus sensores muito mais distantes do que 1 metro (talvez nos cantos da sala) eb) não vai ser tão simples; você provavelmente verá valores bastante diferentes dos sensores, mesmo em uma sala quiescente. É aqui que você joga e experimenta para descobrir como isso realmente funciona!

Também me ocorreu que colocar os fotorresistores a vários metros de distância do ADC envolverá muitos fios, o que adiciona resistência, capacitância e ruído, todos vão interferir em suas medições. Não há muito que você possa fazer sobre isso; você pode brincar um pouco com a medição de resistores de valor conhecido nas pontas dos fios para ver o quão grave é o problema, mas se for terrível, você provavelmente precisará usar um Arduino separado para cada sensor e fazer com que eles se comuniquem de volta com uma central lugar para análise.

Obrigado! Essa informação é muito útil. Eu também estava pensando que talvez eu possa conectar os resistores de uma forma que possa minimizar a quantidade de verificações. Por exemplo, ter 3 em vez de 6 entradas analógicas (cada entrada representando 2 sensores) e dependendo dos valores retornados para ser capaz de dizer qual sensor está recebendo mais luz.
Você poderia tentar encontrar maneiras inteligentes de conectar os fotoresistores em série e / ou paralelo para reduzir o número de amostras que você precisa coletar, mas isso é uma coisa bem complicada de fazer. Eu provavelmente começaria adicionando mais sensores e, se o loop for muito lento devido ao tempo que leva para amostrar todos eles, descobriria um algoritmo para amostrar apenas alguns dos sensores e deixar outros sozinhos com base no que foi amostrado recentemente. Mas primeiro eu faria algo realmente básico funcionar.


Estas perguntas e respostas foram traduzidas automaticamente do idioma inglês.O conteúdo original está disponível em stackexchange, que agradecemos pela licença cc by-sa 3.0 sob a qual é distribuído.
Loading...