Primo progetto: contatore IR per una porta

Ciao a tutti, come primo progetto ho realizzato un sistema composto da due coppie ricevitore-trasmettitore IR (raggio A e raggio B). I due sensori IR sono montati su una porta (assumo che solo una persona alla volta posso attraversare la porta) ed hanno lo scopo di contare le persone all'interno della stanza. Il codice che ho utilizzato è il seguente:

/*                                                                                                            *\
Il seguente codice usa due coppie ricevitore-trasmettitore IR a 38Khz
Ha lo scopo di contare le persone che passano da una porta
Gestisce i seguenti casi:
1) Una persona entra nella stanza
2) Una persona esce dalla stanza
3) Una persona sta entrando nella stanza, cambia idea e torna fuori
4) Una persona sta uscendo dalla stanza, cambia idea e torna dentro
5) Una persona inizia ad entrare/uscire si ferma in mezzo ai sensori per un po' e poi completa l'operazione
\*                                                                                                             */


//pin definitions
#define RXA 12 //TSOP A
#define RXB 10 //TSOP B
#define TX 11 //line for both the IR LED  transmitter
#define SX 2 //this LED is ON if there are people in the room
#define SPY 8 //this LED is ON if both the IR beam are not interrupted

//parameter
const int timeOut = 3000; 

//variables
int count =0; //people in the room
int timerA = 0; //timer for beam A
int timerB = 0; //timer for beam B

//flag
boolean hitA = true; //this is TRUE if RX A is receiving, this is FALSE if the beam A has been broken
boolean hitB = true; //same as above for beam B

boolean enter= false; //flag for somebody entering the room
boolean leave = false; //flag for somedody leaveing the room

boolean transmitting_IR; //transmission flag
boolean receiving_IR; //receiving flag



//turn_off , turn_on, detect functions come as is from
// http://www.eng.utah.edu/~cs1410/Labs/lab09.html
void turn_off_IR ()
{
  // Instead of just adjusting the output on pin 11, this code also
  //   turns off the timer controlling the PWM output on pin 11
  
  TCCR2A = 0; // Disconnect PWM
  TCCR2B = 0; // Stops the timer
  OCR2A = 0;  // No timer top
  digitalWrite(11, LOW);  // Ensure output is off
  
  transmitting_IR = false;
}

void turn_on_IR ()
{
// Set up Timer2 (which can be connected to pins 3 and 11)
  // For full details, see:
  //   arduino.cc/en/Tutorial/SecretsOfArduinoPWM
  // The syntax here has me baffled, but the patterns of usage
  //   are clear if you look at the ATMega328 diagrams.
  //   _BV appears to stand for 'bit value'
  //   Different bits need to be set to control each timer
  //   Refer to diagrams for clarity

  TCCR2A = _BV(WGM21) | _BV(COM2A0); // This mode toggles output once per timer cycle
  TCCR2B = _BV(CS20);  // Do not scale the clock down - use 16 MHz timer rate.
  OCR2A = 210; // Divide sys. clock by 210, 1/2 cycle = 76 khz, 1 cycle = 38 khz
  
  // Output pin 11 should now be emitting a 38 khz signal.
  
  transmitting_IR = true;
}


void detectIR()
{
  // Determine if we are receiving an IR signal.
  //   if pin RXA is false = receiving
  //   if pin RXA is true = not receiving
  
  if(digitalRead(RXA)){
    //Serial.println("missA");
    hitA = false;
  }else{
    hitA = true;
  }
  
  delay(1);
  
  if(digitalRead(RXB)){
    //Serial.println("missB");
    hitB = false;
  }else{
    hitB = true;
  }
}


void pulseIR(){
  //manage the IR transmitter
  if (transmitting_IR)
    turn_off_IR();
  
  if (!transmitting_IR)
    turn_on_IR();     
}


void checkA(){
  //RX routine
  if(leave == false){ // if nobody is going out 
    if(hitA == false && hitB == true){ // and only the INDOOR RX bean has been broken
          if(enter == true){ //if somebody was entering then        
            count ++; // somebody has gone IN
            enter=false;
            updateSx();
            showCount();
          }else{ // if nobody was entering nor leaving then 
            leave = true; // somebody is going OUT
            Serial.println("Leaving...");
            timerA=millis() + timeOut; 
          }
      }
  }
}


void checkB(){
  if(enter == false){ //if nobody is entering 
    if(hitB == false && hitA == true){ // and only the OUTDOOR RX bean has been broken
          if(leave == true){ //if somebody was leaving 
            count --; // somebody has gone OUT
            leave=false;
            updateSx();
            showCount();
          }else{ //if nobody was leaving nor entering then
            enter = true; //somebody is going OUT
            Serial.println("Entering...");
            timerB = millis() + timeOut;
          }
      }
  }
}



void showCount(){
  /*                               *\
  This function will show the count
  \*                               */
  Serial.println(count);
  Serial.println("---------------------------------------------");
  delay(1000);
}

void timeManager(){
  
  int now = millis(); // update current time

  if( (enter == true && now > timerB)  ){ // if enter time out is triggered
      Serial.println("Time Out!"); 
      if(hitA == false && hitB == false){ // if somobody has stopped between the sensors 
        timerB = now + timeOut; // hold the entering state and restart the entering timeOut 
        Serial.println("Both blocked!");  
      }else{
        enter = false;  // the entering beeing has changed is mind and he has come back without entering
      }
  //same for leaving
  }else if( (leave == true && now > timerA)){
     Serial.println("Time Out!"); 
     if(hitA == false && hitB == false){ 
        timerA = now + timeOut;
        Serial.println("Both blocked!");  
     }else{
        leave = false;
     }  
  }

}

void updateSx(){
 if(count > 0){ 
    digitalWrite(SX,HIGH);
   }else{
    digitalWrite(SX,LOW);
   }
}

void updateSpy(){
  if(hitA && hitB){ 
    digitalWrite(SPY,HIGH);
   }else{
    digitalWrite(SPY,LOW);
   }
}


void setup(){  
  pinMode(RXA, INPUT);
  pinMode(TX, OUTPUT);
  pinMode(RXB, INPUT);
  pinMode(SX, OUTPUT);
  pinMode(SPY, OUTPUT);
  digitalWrite(SX, LOW);
  digitalWrite(SPY, LOW);
  
  Serial.begin(9600);
  Serial.println("Ready!");
  pulseIR();
  delay(100);
}

void loop(){
  pulseIR(); // transmit cycle
  detectIR(); // search for IR
  checkA(); // check A IR sensor
  checkB(); // check B IR sensor
  updateSpy(); //upate the spy led
  timeManager(); // check for time out
}

Ho testato il codice su breadboard e pare funzionare bene! Poiché sono nuovo al mondo di Arduino e le mie conoscenze elettroniche sono piuttosto di base, per non parlare della scarsissima esperienza, mi piacerebbe avere i vostri pareri e suggerimenti su come migliorare il progetto o qualunque cosa riteniate utile segnalarmi.

Allego anche uno Fritzing del circuito su cui lavora il codice

Quanto so io la resistenza va sul alimentazione del TSOP e non sull' uscita.
Per aumentare la potenza del IR emanato dai LED IR metterei un transistore NPN.
Ciao Uwe

Progetto interessante. XD
Potresti aggiungere una terza coppia, più in alto delle altre due, per discriminare gli adulti dai bambini.
Ricordo che una cosa del genere era stata fatta in un progetto sperimentale sui varchi di accesso alle ZTL per discriminare la auto da camion e furgoni.
Puoi anche prevedere più porte di accesso/uscita alla stanza.

Ciao.
Paolo.

Grazie mille,
per lo schema di collegamento del TSOP ho fatto riferimento a:
http://www.parallax.com/dl/docs/books/edu/Roboticsv2_2.pdf pag. 252
Anche io pensavo che la resistenza dovesse essere collegata all'alimentazione, però mi sono fidato e funziona. Proverò a cambiare comunque la posizione della resistenza.

Per quanto riguarda il transitore NPN come può aumentare la portata dei led (che è di circa 30 cm) ? Dici di usarlo come amplificatore di corrente?

Ma il fatto che la gente comune ha 2 gambe, ciascuno di noi ha la propria lunghezza del passo, i sensori non vengono ingannati? passo lungo 2 persone - passo corto una persona, il pantalone in fondo oscilla durante la camminata o una gonna :slight_smile:
Se con me porto qualcosa dentro la stanza o esco con una scatola o un abito in mano magari lungo, non inganno i sensori?
non è semplice stabilire costantemente quante persone ci sono in una stanza o se è vuota, mi sa che devi resettare spesso il sistema.

ciao

Non penso che questa cosa dell'altezza funzioni... Mentre per i veicoli i parametri sono standard per le persone vedo qualche difficoltà... Ci sono bambini di 10 anni che sono più alti di me..... :stuck_out_tongue: è vero anche il contrario.. Sono io ad essere basso :fearful: XD

pablos:
Ma il fatto che la gente comune ha 2 gambe, ciascuno di noi ha la propria lunghezza del passo, i sensori non vengono ingannati? passo lungo 2 persone - passo corto una persona, il pantalone in fondo oscilla durante la camminata o una gonna :slight_smile:
Se con me porto qualcosa dentro la stanza o esco con una scatola o un abito in mano magari lungo, non inganno i sensori?
non è semplice stabilire costantemente quante persone ci sono in una stanza o se è vuota, mi sa che devi resettare spesso il sistema.

Tutti questi casi non sono gestiti certo, i sensori sono facili da ingannare anche se pensavo di piazzarli ad altezza delle spalle di una persona per non soffrire il problema delle 2 gambe :wink:

Per il fatto degli oggetti andrebbe testato, ma credo che sia abbastanza robusto da questo punto di vista, dato che il sistema può essere solo in tre stati, qualcosa sta entrando (e non qualcosa sta entrando due volte) e qualcosa sta uscendo, ci sono dei timeOut per il tempo di attraversamento... Però non ci scommetterei la casa! Ripeto lo dovrei testare in situazioni simili.

IngHooch:
Grazie mille,
per lo schema di collegamento del TSOP ho fatto riferimento a:
http://www.parallax.com/dl/docs/books/edu/Roboticsv2_2.pdf pag. 252
Anche io pensavo che la resistenza dovesse essere collegata all'alimentazione, però mi sono fidato e funziona. Proverò a cambiare comunque la posizione della resistenza.

Per quanto riguarda il transitore NPN come può aumentare la portata dei led (che è di circa 30 cm) ? Dici di usarlo come amplificatore di corrente?

Secondo me fa fede lo datasheet. Visto che non so che modello é il Tuo TSOP non so dirlo con certezza. Ho usato un TSOP31238 e lí il datasheet prevede una resistenza tra 33 Ohm e 1kOhm (application circuit sulla prima pagina in basso a destra di http://www.vishay.com/docs/81745/tsop312.pdf )

Con un transistore puoi dare piú corrente e il IRLED da piú luce. I IRLED a secondo il modello sopportano anche 100mA e se li metti una alternata con duty cycle 50% puoi raddoppiare tale corrente. percui 200mA. Un uscita Arduino può dare 40mA e percui 20mA per IRLED.

Ciao Uwe

Grazie della dritta!
Mi procurerò il necessario per fornire più corrente ai LED e vedo che portate ottengo.

Per il futuro farò riferimento al datasheet piuttosto che a generici schemi trovati in giro!
Grazie ancora.

Ho una domanda, esistono degli interruttori (cose tipo relè immagino) controllabili con Arduino (insomma con le uscite generabili da Arduino). Per esempio se volessi controllare un interruttore delle lampade di casa (220 V) con un consenso di Arduino (5 V) che cosa mi servirebbe?

IngHooch:
Ho una domanda, esistono degli interruttori (cose tipo relè immagino) controllabili con Arduino (insomma con le uscite generabili da Arduino). Per esempio se volessi controllare un interruttore delle lampade di casa (220 V) con un consenso di Arduino (5 V) che cosa mi servirebbe?

esistono i relé reed che consumano abbastanza poco da essere pilotabili direttamente con Arduino ma non vanno bene per carichi 220, o almeno quelli che ho io riportano 110V, e comunque sopportano carichi bassi; la cosa più corretta sarebbe usare, per ogni comando da pilotare, un fotoaccoppiatore ed un rele comune oppure meglio ancora sarebbe un relé a stato solido o più semplicemente un TRIAC; insomma soluzioni ce ne stanno tante, si tratta anche di capire cosa devi fare esattamente, che carichi devi pilotare e per quanto tempo, ecc.

Grazie, la domanda era sorta nella remota ipotesi che il contatore sulla porta funzioni in maniera robusta, potrei spegnere (il generale luci?) le luci della stanza quando nessuno è dentro e riaccenderle quando entra qualcuno.
Ci tengo a precisare che (almeno per il momento) non intendo usare il progetto per questo scopo, era giusto una curiosità per capire le potenzialità di Arduino.

IngHooch:
Grazie, la domanda era sorta nella remota ipotesi che il contatore sulla porta funzioni in maniera robusta, potrei spegnere (il generale luci?) le luci della stanza quando nessuno è dentro e riaccenderle quando entra qualcuno.
Ci tengo a precisare che (almeno per il momento) non intendo usare il progetto per questo scopo, era giusto una curiosità per capire le potenzialità di Arduino.

Spegnere il generale luci significherebbe montare il componente in serie al magnetotermico, se ti riferisci all'intero appartamento, mi pare un po' complessa come soluzione, dal punto di vista realizzativo; se invece parli della famosa stanza allora ti basta interrompere il filo che va al lampadario, ma così il controllo sarebbe totale da parte del tuo circuito, oppure dovresti realizzare uno schema a doppio interruttore (hai presente il corridoio che ti permette di accendere e spegnere una lampadina con due o più intetturroi separati?) di cui uno sarebbe quello originale della stanza e l'altro il tuo componente, mi sembra più elegante.

Mi piace questa soluzione, posso realizzarla con un TRIAC?

si, il circuitino è semplice, tipo questo:

questo però è optoaccoppiato

BrainBooster:
si, il circuitino è semplice, tipo questo:

questo però è optoaccoppiato

come stadio per Arduino mi sembra ottimo, ma lui ora si riferisce al fatto di poter pilotare il lampadario indifferentemente dall'interruttore della stanza e/o da Arduino. Finche si tratta di un impianto tutto a 220 o tutto in bassa tensione ci siamo ma qui ora siamo con una situazone ibrida; allora conviene usare questo schema per creare un "pulsante" a 220V, sostituire l'interruttore di casa con un pulsante e pilotare con entrambi uno di quei relé che si usano ora in quelle situazioni, quei relé tipo flip-flop, che cambiano stato ad ogni impulso

Grazie ad entrambi, credo di essermi fatto un'idea piuttosto chiara di come la cosa potrebbe funzionare.