Sensore PIR

Salve a tutti! Ho di recente acquistato su ebay un sensore di movimento PIR, modello HC-SR501, per completare un progetto che dovrò consegnare all'esame di laboratorio di automatica.
Il progetto è abbastanza semplice (sono alle prime armi infatti!).
C'è questo sensore PIR, e ogni volta che tale sensore rileva il movimento, dovrebbe accendersi un led, e sul display collegato ad Arduino dovrebbe andare avanti un contatore.
Quando sul display viene raggiunta la cifra massima, il led dovrebbe rimanere acceso fisso, e uno speaker dovrebbe emettere un suono per 2 secondi.
Al termine di questa operazione, il contatore si dovrebbe azzerare, per poi ricominciare tutto dall'inizio.
Ho anche aggiunto 3 pulsanti, per il controllo manuale di questo contatore.
Parlo al condizionale perchè purtroppo ho riscontrato problemi con il sensore.
Infatti, anche se nella camera non si muove nulla, il contatore continua ad incrementare i valori, e non riesco a capire il perchè! Ho utilizzato una resistenza da 100Kohm, ma sembra come impazzito!
E la cosa strana è che se non chiedo di stampare nulla, il sensore funziona perfettamente.
Help!!

Scusate, la resistenza è da 10Kohm!

puoi disegnare uno schema del collegamento pir-arduino?

m_ri:
puoi disegnare uno schema del collegamento pir-arduino?

sopratutto posta il codice di solito è li l'errore :smiley:

Certo!
Allora, ho collegato il GND del sensore, alla messa a terra di Arduino, i 5V, ai 5 volt di Arduino, mentre l'OUT del sensore l'ho collegato al pin di arduino e alla resistenza da 10Kohm, che scarica a terra.
Sto provando a postare una fotografia, ma ci sta mettendo veramente troppo!

Ed ecco il codice!

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int sensorPIR = 1;
const int ledVerde = 13;
const int ledRosso = 8;
const int speaker = 9;
const int pulsante_meno = 6;
const int pulsante_piu = 7;
const int pulsante_reset = 10;
int count = 0;

void setup ()
{
pinMode(sensorPIR, INPUT);
pinMode(ledVerde, OUTPUT);
pinMode(ledRosso, OUTPUT);
pinMode(speaker, OUTPUT);
pinMode(pulsante_meno, INPUT);
pinMode(pulsante_piu, INPUT);
pinMode(pulsante_reset, INPUT);
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("CONTATORE:");
lcd.setCursor(0,1);
lcd.print("0");
}

void loop()
{
digitalWrite(ledVerde, LOW);
digitalWrite(ledRosso, LOW);
int val_piu = digitalRead(pulsante_piu);
int val_meno = digitalRead(pulsante_meno);
lcd.setCursor(0,1);
lcd.print(count);

int valore = digitalRead(sensorPIR);
if(valore == HIGH) //Ciò che segue avviene solo se il sensore rileva movimento
{
if (count < 5)
{
count++;
digitalWrite(ledVerde, HIGH);
digitalWrite(ledRosso, LOW);
noTone(speaker);
lcd.setCursor(0,1);
lcd.print(count);
delay(600);
}

else
{
tone(speaker, 4000, 2000);
digitalWrite(ledRosso, HIGH);
digitalWrite(ledVerde, LOW);
delay(2000);
lcd.clear();
lcd.print("STOP!");
delay(2000);
lcd.clear();
lcd.print("CONTATORE:");
lcd.setCursor(0,1);
lcd.print("0");
count=0;
}
}
]

complimenti per il codice non me lo aspettavo cosi pulito,ordinato e ben fatto ,però a quanto pare avevo ragione ho già aiutato un altro utente del forum sul sensore PIR il PIR va calibrato prima di essere utilizzato.
Un attimo che ti recupero il codice per farlo :wink:
ps 1 Per le prossime volte ti consiglio di utilizzare le sezioni apposite software e hardware questa è la sezione generale.
ps 2 per le prossima volte usa il tag code(quello con l'icona del cancelletto) per inserire il codice in questo modo risulta più leggibile.

Edit:
Il link è al playground una grande risorsa di arduino ti ocnsiglio di consultarla quando hai problemi.
http://arduino.cc/playground/Code/PIRsense

/* 
 * //////////////////////////////////////////////////
 * //making sense of the Parallax PIR sensor's output
 * //////////////////////////////////////////////////
 *
 * Switches a LED according to the state of the sensors output pin.
 * Determines the beginning and end of continuous motion sequences.
 *
 * @author: Kristian Gohlke / krigoo (_) gmail (_) com / http://krx.at
 * @date:   3. September 2006 
 *
 * kr1 (cleft) 2006 
 * released under a creative commons "Attribution-NonCommercial-ShareAlike 2.0" license
 * http://creativecommons.org/licenses/by-nc-sa/2.0/de/
 *
 *
 * The Parallax PIR Sensor is an easy to use digital infrared motion sensor module. 
 * (http://www.parallax.com/detail.asp?product_id=555-28027)
 *
 * The sensor's output pin goes to HIGH if motion is present.
 * However, even if motion is present it goes to LOW from time to time, 
 * which might give the impression no motion is present. 
 * This program deals with this issue by ignoring LOW-phases shorter than a given time, 
 * assuming continuous motion is present during these phases.
 *  
 */

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;        

//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 5000;  

boolean lockLow = true;
boolean takeLowTime;  

int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;


/////////////////////////////
//SETUP
void setup(){
  Serial.begin(9600);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    Serial.println("SENSOR ACTIVE");
    delay(50);
  }

////////////////////////////
//LOOP
void loop(){

     if(digitalRead(pirPin) == HIGH){
       digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
       if(lockLow){  
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;            
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec"); 
         delay(50);
         }         
         takeLowTime = true;
       }

     if(digitalRead(pirPin) == LOW){       
       digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){  
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;                        
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
           }
       }
  }

Se non riesci ad adattarlo ai tuoi scopi o a capirlo chiedi pure :wink:

Ora leggo tutto quanto il codice con calma e se ho problemi ti faccio sapere! E grazie mille per il complimento! Non ho mai programmato in vita mia, e prima di iniziare ad utilizzare Arduino non sapevo nemmeno come fosse fatta una resistenza! (E ti assicuro che tutto quello che ho fatto l'ho scritto di mio pugno, cercando disperatamente su libri e su internet! Per cui grazie davvero! :slight_smile:

Ok perdona l'ultima domanda idiota!
Questo codice devo usarlo a parte, per calibrare il sensore, o devo aggiungerlo proprio al codice che ho già scritto? Cioè basta che lo carico una volta su Arduino, e poi non serve più?!

sara92:
Ok perdona l'ultima domanda idiota!
Questo codice devo usarlo a parte, per calibrare il sensore, o devo aggiungerlo proprio al codice che ho già scritto? Cioè basta che lo carico una volta su Arduino, e poi non serve più?!

Tranquilla,
Allora arduino può eseguire un solo sketch(codice) di conseguenza devi unirlo al tuo,ovvero col tuo codice calibri prima il sensore nel setup(come fa lui) poi utilizzi il pir come già fai.
Devi integrare la funzione di calibrazione nel tuo sketch.
Vorrei che ci arrivassi tu cosi memorizzi meglio la cosa praticamente devi aggiungere questo nel tu void setup in modo che vegna eseguito prima di entrare nel loop:

 //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    Serial.println("SENSOR ACTIVE");
    delay(50);
  }

Naturalemnte dichiarando le variabili che usa anche lui.
Se ti controlli il resto del codice lui fa anche molti altri controlli per evitare errori,studiati bene il codice e integralo al tuo. :wink:
Se proprio non ci riesci chiedi :grin:

D'accordo grazie :slight_smile: ti chiederò ancora solo se indispensabile :slight_smile:

Ciao Sara

Il sensore da come segnale di Output High 3,3V. Dovrebbero bastare perché Arduino lo riconosca come HIGH. Controlla con un multimetro se la tensione é giusta.
Dalla descrizione (per esempio http://www.imediabank.com/imbstore/index.php?route=product/product&product_id=65) risulta che non ti serve una resistenza aggiuntiva verso massa o verso i 5V.
Il sensore all'accensione si autocalibra e non mistura. Anche a Arduino serve un po di tempo perche il bootloader abbia terminato i suoi controlli iniziali. Al limite aggiungi un delay (2000) nel setup().

Il Tuo codice ha un errore di concetto. Tu vuoi contare quante volte il sensore vede qualcuno (quante volte passa da LOW a HIGH) Il Tuo codice legge a ogni passaggio di loop() che avviene ogni 0,6 secondi se il sensore é attivato e incremente il contatore.
Devi usare una variabile di stato e controllare se la prima volta che leggi HIGH il sensore incrementi il contatore. Un passaggio H-L resetta la variabile di stato.

int status =0;
...
loop()
...
int valore = digitalRead(sensorPIR);
  if(valore == HIGH && stato ==0) //il primo giro 
  {
    stato = 1;
    if (count < 5)
    {
      count++;
      digitalWrite(ledVerde, HIGH);
      digitalWrite(ledRosso, LOW);
      noTone(speaker);
      lcd.setCursor(0,1);
      lcd.print(count);
      delay(600);
    }
else {....}
 if(valore == LOW && stato ==1) //il primo giro 
    {
    stato =0;
    }

Ciao Uwe

Signor Uwe,
non vorrei sbagliare ma lei si sta sbagliando :grin:
Se guardi bene lei fà

  if(valore == HIGH) //Ciò che segue avviene solo se il sensore rileva movimento
  {
    if (count < 5)

fa logica sul secondo count praticamente se il valore è low non fa niente(non azzera niente,anche perchè non credo che una persona passi in 0,6 secondi,a me no che non sia speedy gonzales :stuck_out_tongue_closed_eyes:) ,se invece e high ed e minore di 5 incrementa il count se e high e maggiore di 5 entra nell'else.

ps l'aggiunta nel setup che le avevo consigliato serviva a quello :grin:
(ovvero il tempo di attesa di calibrazione del pir,anche se non pensavo bastasse quello quindi Sara(se ci leggi :grin: ) prova ad aggiungere solo quella parte nel void setup)

Aiuto, mi danno del signore. :astonished: :astonished:
Non vedo l' errore di concetto che mi spieghi.

Se qualcuno mantiene il pulsante premuto per piú di 0,6 secondi il contatore viene incrementato piú di una volta.
Indipendentemente dalla propia imaginazione che qualcuno potrebbe farlo o no é opportuno prevedere tutte le possinbilitá e realizzare un codice che é immune a dei usi sbagliati o improbabili (a prova di idiota).

Ciao Uwe

uwefed:
Aiuto, mi danno del signore. :astonished: :astonished:
Non vedo l' errore di concetto che mi spieghi.

Se qualcuno mantiene il pulsante premuto per piú di 0,6 secondi il contatore viene incrementato piú di una volta.
Indipendentemente dalla propia imaginazione che qualcuno potrebbe farlo o no é opportuno prevedere tutte le possinbilitá e realizzare un codice che é immune a dei usi sbagliati o improbabili (a prova di idiota).

Ciao Uwe

Anche questo è vero,ci vuole sempre il codice a prova di utonto :smiley: intendevo che il codice in fondo non è sbagliato se lo stato passa a low non viene azzerato niente quindi e teoricamente corretto ma praticamente può risultare errato.

Devo ammettere che mi sento un pò confusa in questo momento XD comunque...non so se questo può aiutarvi ad aiutarmi, ma questo benedetto sensore PIR fa il pazzo solo quando nel codice viene chiesto di stampare o sul display, o sul serial monitor, perchè altrimenti funziona correttamente...accende il led e lo speaker quando rileva del movimento...mentre basta anche solo scrivere in SETUP la funzione Serial.begin(9600), perchè questo si comporti come se rilevasse sempre il movimento.
Non capisco proprio perchè faccia così, sembra come se entrasse in conflitto con la sola istruzione stampa... non ho ancora provato a fare nulla di quello che mi avete detto, però intanto vi scrivo questo mio dubbio!
Non so se sono stata chiara, e mi spiace se ho usato termini inappropriati come funzioni e istruzioni ecc :s

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int sensorPIR = 1;
const int ledVerde = 13;
const int ledRosso = 8;
const int speaker = 9;
const int pulsante_meno = 6;
const int pulsante_piu = 7;
const int pulsante_reset = 10;
int count = 0;

Perchè hai collegato il sensore sul pin 1 che è quello utilizzato per mandare i dati al pc.
Ciao

Stai usando il sensore con il Pin 1

I Pin 0 e 1 sono quelli usati dalla seriale.
Dovresri spostare il PIr sul pin A0 e cambiare l'assegnazione

const int sensorPIR = 14; // Pin A0

Ho fatto come mi avete detto voi e funziona! L'errore stava nel fatto che l'avevo collegato al pin 1! Ora devo sistemare i valori dei secondi, perchè sono un pò sballati, ma il problema più grande me l'avete risolto!
Non so come ringraziarvi :D:D:D

Non so come ringraziarvi :D:D

Lo hai già fatto,buon lavoro.