Go Down

Topic: Testes ao PIR SE-10 com resultados preocupantes (Read 2436 times) previous topic - next topic

xaral

Apr 27, 2012, 06:49 pm Last Edit: Apr 27, 2012, 07:15 pm by xaral Reason: 1
Olá malta

Eu estou a desenvolver um projeto em que uso os sensores de movimento PIR para detetar a presença de pessoas numa sala. Eu optei pela compra do SE-10 disponibilizado pela http://www.sparkfun.com/products/8630.

Apesar de o sensor ser bastante simples e de fácil funcionamento, estou obtendo resultados pouco positivos.
Esta manhã estive a fazer uns testes, colocando o sensor no interior de uma caixa envolto em plástico.

Seria de prever que não fosse detetado movimento, mas os resultados foram os seguintes:
em 1275 iterações, os sensor diz ter detetado movimento em 140 das vezes , o que dá uma percentagem de 10% de erro!!!

Eu segui o esquema de funcionamento de um coletor aberto com uma resistência de pullup de 10k ohms segundo sugerido pelo sítio http://bildr.org/2011/06/pir_arduino/

Será este um defeito do sensor?eu tentei com dois e ambos dão este erro...
:smiley-roll-blue: :smiley-roll-blue:

A única coisa que consigo pensar é que a caixa é demasiado pequena.
Já experimentaste num quarto durante a noite, por exemplo?
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

xaral

Pode ser uma boa sugestão. segunda feira faço o teste e digo-te as conclusões a que cheguei
;)

Já agora por curiosidade aqui fica o código que utilizei

Code: [Select]
int calibrationTime = 60;       

int pirPin1 = 2; //digital 2

int LED1 = 4;
int n_detecoes=0;
int n_iteracoes=0;
int per_detecoes=0;

 
void setup()
{
  Serial.begin(9600);
  pinMode(pirPin1,INPUT);

  pinMode(LED1,OUTPUT);

  digitalWrite(LED1,LOW);

  //give the sensor some time to calibrate
  Serial.println("Sensor Calibration in Progress");
  Serial.println("------------------------------");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    digitalWrite(LED1, HIGH);
    delay(250);
    digitalWrite(LED1, LOW);
    delay(250);
  }

  Serial.println("");
  Serial.println("Sensor Calibration Completed");
  Serial.println("Sensor Reading Active");
  delay(50);
 
}

void loop()
{
  int pirVal1 = digitalRead(pirPin1);
 
  if(pirVal1 == LOW)
  {
    //was motion detected
    Serial.print(pirVal1);
    Serial.print(';');
   
    n_detecoes=n_detecoes+1;
    Serial.print(n_detecoes);
    Serial.print(';');
   
    digitalWrite(LED1,HIGH);
    delay(2000);
  }
    else
    {
    Serial.print(pirVal1);
    Serial.print(';');
    Serial.print(n_detecoes);
    Serial.print(';');

   
    digitalWrite(LED1,LOW);
    delay(2000);
    }
   
    n_iteracoes +=1;
    Serial.print(n_iteracoes);
    Serial.print(';');
    per_detecoes =(n_detecoes*100)/n_iteracoes;
    Serial.print(per_detecoes);
    Serial.println(';');
}

O código parece-me correcto. Não vejo erros nenhuns lá.

Os PIR funcionam por temperatura, a caixa esteve sujeita a alguma diferença de temperatura?
Algo que a sparkfun não tem é o campo de visão deste sensor, que indica o alcance e qual a maneira como a sensibilidade do sensor é distribuída. Isso seria mais ou menos importante para assumir que a caixa é pequena demais e interfere com o campo de visão.

O ideal é mudar as variáveis para unsigned long e deixar isso a rolar numa sala vazia durante a noite.
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

xaral

Obrigado pela resposta Bubu

A caixa é feita em papelão e não tem qualquer diferença de temperatura brusca, só se houver por aqui fantasmas :)

Já tentei arranjar o tal alcance e sensibilidades dos sensores, mas o fabricante, meio chinês meio coreano,  não responde...

Vou seguir a tua sugestão e ver quais são os resultados numa sala escura...

Edsoncan

#5
Apr 30, 2012, 01:06 pm Last Edit: Apr 30, 2012, 01:45 pm by Edsoncan Reason: 1
Um sensor PIR funciona por variação de infravermelho, as fontes podem ser muitas, uma janela aberta por exemplo.
O sistema de detecção compara um sinal através de um integrador com o sinal normal, se houver diferença significa que algo penetrou no campo, se a variação for lenta ele não dispara, pois o integrador se ajusta ao novo valor, se a variação for rápida, significa que algo que emite infravermelho penetrou no campo de detecção.
Alguns anos atras desenvolvemos esse sensor que une micro-ondas com infravermelho, pois se você colocar uma madeira na frente do corpo o sensor de infravermelho não detecta nada, pois a fonte de calor fica bloqueada, já o de micro-ondas detecta:
http://www.eck-projeto-eletronico.com.br/2011/04/05/eck-desenvolveu-um-projeto-de-eletronica-sensor-presenca-com-micro-ondas-e-infravermelho/
Edson

xaral

Olá de novo pessoal!
Parece que o Bubu acertou em cheio no problema. Quando coloquei o sensor numa sala escura ele já não detetou qualquer movimento inexistente :)

Só tive pena de passar algumas vezes por ele e o sensor não me detetar :(
Poderá ser do delay ser 2000?

Obrigado a todas pela ajuda

He shoots, he scores... :)

Quando vi o delay no código pensei isso mesmo... mas depois pensei que não querias contar o mesmo pulso mais que uma vez e meteste o delay.

Já experimentaste contar por flancos?

Code: [Select]

sensor = digitalRead(PIR);
char flanco=0;

if (sensor == HIGH && flanco == 0) {
    flanco = 1;
    hits++;
    }
if (sensor == LOW) {flanco = 0;}


Outra hipótese mais engracada e talvez mais simples de codificar seria ligar o sensor a um dos pinos dos temporizadores (T1 ou T2 se precisares do millis()) e usares o relógio como contador de eventos. Aí não terias problemas já que o relógio conta apenas nas transicões.
Depois era tão simples como:

Code: [Select]


set_cnt(unsigned int value) {
TCNTx = value;
}

unsigned int read_cnt() {
return TCNTx;
}

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

xaral

Estou a ver que dominas bem mais que eu o arduino  XD

Não estou a entender bem nem os objetivos do flanco nem da segunda opção que sugeres...

A primeira opção é contar as transições de LOW para HIGH em vez de contar o número de vezes que o sinal está activo. Esse PIR mantém o sinal activo durante um segundo sempre que detecta alguém. Se o arduino estiver sempre a correr (sem o delay), vai contar várias vezes a mesma detecção. Se incrementares o contador sempre que o sinal do sensor passar de 0 para 1, estás descansado porque não conta a mesma detecção mais que uma vez.

A segunda opção implica algum conhecimento dos timers. Mas basicamente os timers do Arduino podem ter várias fontes de "temporização". Se reparares no manual, diz Timer/Counter. Isto significa que na realidade o que chamamos de timer é um counter... se dermos um sinal com uma determinada frequência a esse contador, estamos efectivamente a contar tempo.

No entanto, o Arduino permite usar um dos pinos dos microcontrolador como fonte para esse contador. Assim sendo, sempre que existe uma transição de baixo para alto nesse pino o contador incrementa automaticamente. Estranhamente não consegui encontrar exemplos para isto na net. :|
Amanhã posso dar uma vista de olhos ao manual e meter aqui uma configuração do timer para exemplificar este modo. Nota que isto faz com que não possas usar PWM ou millis dependendo do timer que usares para contar os eventos.
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

neuron_upheaval

#10
May 03, 2012, 05:41 am Last Edit: May 03, 2012, 05:44 am by neuron_upheaval Reason: 1
Olá

Estou vendendo um produto no MercadoLivre Brasil que usa exatamente essas peças que usastes no teu projecto: Arduino Uno, SE-10, um breadboard, alguns fios, dois resistores (um deles para o pull-up) e um LED (para depurações de erros ;) ).

No meu caso, o sensor funciona bem até mesmo em locais com iluminação.

Por que não usas a função pulseIn() do Arduino, em vez de esperar por um LOW e depois um HIGH?

http://arduino.cc/en/Reference/pulseIn

Os meus SE-10 fornecem um pulso LOW de aproximadamente 900 ms quando há detecção.

O inconveniente do SE-10 é que o alcance dele é de apenas 2-3 metros.

[]s

neuron_upheaval


Por que não usas a função pulseIn() do Arduino, em vez de esperar por um LOW e depois um HIGH?

http://arduino.cc/en/Reference/pulseIn


O problema do pulse in é que bloqueia o programa...

Code: [Select]
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution.  calling
// digitalRead() instead yields much coarser resolution.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
unsigned long width = 0; // keep initialization out of time critical area

// convert the timeout from microseconds to a number of times through
// the initial loop; it takes 16 clock cycles per iteration.
unsigned long numloops = 0;
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;

// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask)
if (numloops++ == maxloops)
return 0;

// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask)
if (numloops++ == maxloops)
return 0;

// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask) {
if (numloops++ == maxloops)
return 0;
width++;
}

// convert the reading to microseconds. The loop has been determined
// to be 20 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
return clockCyclesToMicroseconds(width * 21 + 16);
}


Ou seja, apesar do timeout, etc... é processamento desperdicado. Além do facto que o pulseIn não garante contagem dum impulso. Basta que o impulso aconteca logo após um timeout e pronto... perdeu-se esse impulso.

Daí que testar o flanco (que é o que se pretende, em vez da duracão do impulso) seja uma melhor solucão. Ainda assim, a minha preferida é a do timer como contador.

Desculpa não ter dado uma vista de olhos ainda acerca de como o configurar. Vou tentar ver isso hoje.
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

xaral

Mais uma vez agradeço toda a vossa ajuda!
Antes de responder às vossas sugestões gostaria de vos dizer que experimentei outra alternativa, utilizar a entrada analógica do arduino para ver como reagia o sensor. Pois bem, com este novo código ele deteta bem o movimento, o que me faz pensar que o problema do códiog que vos mostrei deve ser mesmo o delay...

Em relação às vossas 3 sugestões, pelo que entendi, sugerem que em vez de trabalhar com o HIGH e o LOW que o sensor devolve, que use o tempo entre as deteções de forma a evitar que este repita resultados certo??

Ainda estou a tentar colocar os códigos com as vossas sugestões a funcionar, pois são coisas novas que sem vocês não descobriria :)

xaral

Desculpa bubu mas não tinha visto a tua última mensagem...

Fico à espera da tua configuração

neuron_upheaval

#14
May 03, 2012, 01:06 pm Last Edit: May 03, 2012, 01:09 pm by neuron_upheaval Reason: 1


Por que não usas a função pulseIn() do Arduino, em vez de esperar por um LOW e depois um HIGH?

http://arduino.cc/en/Reference/pulseIn


O problema do pulse in é que bloqueia o programa...

[code snipped]

Ou seja, apesar do timeout, etc... é processamento desperdicado. Além do facto que o pulseIn não garante contagem dum impulso. Basta que o impulso aconteca logo após um timeout e pronto... perdeu-se esse impulso.

Daí que testar o flanco (que é o que se pretende, em vez da duracão do impulso) seja uma melhor solucão. Ainda assim, a minha preferida é a do timer como contador.

Desculpa não ter dado uma vista de olhos ainda acerca de como o configurar. Vou tentar ver isso hoje.

Mas o fato de o pulseIn() pausar o programa é indiferente se o programa depende exclusivamente da detecção do sensor para fazer o que precisa; além do mais, Serial.print()'s e delay()'s também bloqueiam o programa

Se queres algo que realmente execute apesar dos bloqueios no programa, usa interrupções:

http://arduino.cc/en/Reference/AttachInterrupt

Go Up