Pages: 1 ... 9 10 [11] 12   Go Down
Author Topic: sensori per ostacoli  (Read 11076 times)
0 Members and 1 Guest are viewing this topic.
Napoli
Offline Offline
Full Member
***
Karma: 0
Posts: 200
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vanno bene questi secondo voi?

http://cgi.ebay.it/8x-L-516-INFRARED-EMITTING-DIODE-IR-Emitter-/170422999871?pt=LH_DefaultDomain_212&hash=item27ae009b3f#ht_840wt_905
Logged

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10525
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

eccomiii!!!!
finalmente ho avuto la voglia di scrivere la classe.... come al solito NON è testata, perché non ho i pezzi... se mi fate un po' di debug mi fate un favore, che la mettiamo nel playground

ERER.cpp
Code:
#import "ERER.h"

/*
  ERER.cpp - Library for ERER sensors.
  (use 2 infrared LEDs to build a distance sensor)
  Rewritten by Mauro Mombelli 03/04/2011
  Based on code of Giovanni Blu Mitolo, March 11, 2011.
  Released with Creative Commons Attribution licence  
*/

volatile byte _oldbit;
byte _changed, _newbit;
volatile boolean _hasChanged=false;
volatile long rawDistance=0;
volatile byte BCDreceiverN, BCDreceiverP, BCDemitterP;
volatile byte MASKreceiverN, MASKemitterP, MASKreceiverP;
volatile boolean emitterStatus;
unsigned long _time;
unsigned long _startIn[2];
unsigned long _rawIn[2];

ERER::ERER(byte PCINTemitterP, byte PCINTreceiverP, byte PCINTreceiverN){

  //set emitterP pin mode
  BCDemitterP = getBCDpin(PCINTemitterP); //find BCD (see PortManipulation)
  MASKemitterP = (1<< (PCINTemitterP - (8*BCDemitterP) ) ); //find MASK for esy port manipulation
  //set as OUTPUT and HIGH
  switch (BCDemitterP){
    case 0:
      DDRB |= MASKemitterP;
      PORTB |= MASKemitterP;
      break;
    case 1:
      DDRC |= MASKemitterP;
      PORTC |= MASKemitterP;
      break;
    case 2:
      DDRD |= MASKemitterP;
      PORTD |= MASKemitterP;
      break;
  }
  emitterStatus=true;
  
  //set receiverP pin mode
  BCDreceiverP = getBCDpin(PCINTreceiverP); //find BCD (see PortManipulation)
  MASKreceiverP = (1<< (PCINTreceiverP - (8*BCDreceiverP) ) ); //find MASK for esy port manipulation
  //set as OUTPUT and LOW
  switch (BCDreceiverP){
    case 0:
      DDRB |= MASKreceiverP;
      PORTB &= ~MASKemitterP;
      break;
    case 1:
      DDRC |= MASKreceiverP;
      PORTC &= ~MASKemitterP;
      break;
    case 2:
      DDRD |= MASKreceiverP;
      PORTD &= ~MASKemitterP;
      break;
  }
  
  //set PCINTreceiverN as INPUT AND attach Interrupt
  /*
  remember:
  PORTB maps to Arduino digital pins 8 to 13 (PCIE0) form PCINT0 to PCINT7
  PORTC maps to Arduino analog pins 0 to 5 (PCIE1) form PCINT8 to PCINT14
  PORTD maps to Arduino digital pins 0 to 7 (PCIE2) form PCINT16 to PCINT23
  */
  BCDreceiverN = getBCDpin(PCINTreceiverN);
  MASKreceiverN = (1<< (PCINTreceiverN - (8*BCDreceiverN) ) ); //find MASK for esy port manipulation
  
  switch (BCDreceiverN){
    case 0:
      PORTB &= ~MASKreceiverN;//set as INPUT
      PCICR |= (1 << PCIE0); //INTERRUPT ON PCIE0 CHANGE ACTIVATED
      PCMSK0 |= MASKreceiverN; //UMASKING INTERRUPT FOR PIN
      _oldbit = PINB;//To understand witch pin has changed
      break;
    case 1:
      PORTC &= ~MASKreceiverN;//set as INPUT
      PCICR |= (1 << PCIE1); //INTERRUPT ON PCIE0 CHANGE ACTIVATED
      PCMSK1 |= MASKreceiverN; //UMASKING INTERRUPT FOR PIN
      _oldbit = PINC;//To understand witch pin has changed
      break;
    case 2:
      PORTD &= ~MASKreceiverN;//set as INPUT
      PCICR |= (1 << PCIE2); //INTERRUPT ON PCIE0 CHANGE ACTIVATED
      PCMSK2 |= MASKreceiverN; //UMASKING INTERRUPT FOR PIN
      _oldbit = PIND;//To understand witch pin has changed
      break;
  }
  
  //charge ReceiverN using internal pull-up
  setStatus(BCDreceiverN, MASKreceiverN, true);
  //stop charge ReceiverP
  setStatus(BCDreceiverN, MASKreceiverN, false);
}

long ERER::getRawDistance(){
  return rawDistance;
}

byte ERER::getBCDpin(byte PCINTpin){
  if (PCINTpin>=0 && PCINTpin<=7){
    return 0;
  }
  
  if (PCINTpin>=8 && PCINTpin<=14){
    return 1;
  }
  
  if (PCINTpin>=16 && PCINTpin<=23){
    return 2;
  }
  return 3;  
}

void ERER::setStatus(byte BCD, byte MASK, boolean state){
  if (state){
    switch (BCD){
      case 0:
      PORTB |= MASK;
      break;
    case 1:
      PORTC |= MASK;
      break;
    case 2:
      PORTD |= MASK;
      break;
    }
  }else{
    switch (BCD){
      case 0:
      PORTB &= ~MASK;
      break;
    case 1:
      PORTC &= ~MASK;
      break;
    case 2:
      PORTD &= ~MASK;
      break;
    }
  }
}

ISR(PCINT2_vect) {
  if (BCDreceiverN == 2){
    _newbit=PIND;
    _changed=_newbit^_oldbit;
  
    if (_changed & MASKreceiverN){//if PCINTreceiverN has changed
      _time=micros();
      _hasChanged=true;
      
      if (_newbit & MASKreceiverN) { //if PCINTreceiverN now is high
        _startIn[emitterStatus]=_time;
      }else{
        _rawIn[emitterStatus]=_time-_startIn[emitterStatus];
      
        if (!emitterStatus){ //if we read with emitter HIGH and then LOW we have a distace
          rawDistance = _rawIn[0]-_rawIn[1]; //because dark read teorically is lower than light read
        }
      
        //start a new reading changing emitter status
        emitterStatus!=emitterStatus;
        if (emitterStatus){
          switch (BCDemitterP){
            case 0:
              PORTB |= MASKemitterP;
              break;
            case 1:
              PORTC |= MASKemitterP;
              break;
            case 2:
              PORTD |= MASKemitterP;
              break;
          }
        }else{
          switch (BCDemitterP){
            case 0:
              PORTB &= ~MASKemitterP;
              break;
            case 1:
              PORTC &= ~MASKemitterP;
              break;
            case 2:
              PORTD &= ~MASKemitterP;
              break;
          }
        }
    
        //charge ReceiverN using internal pull-up
        PORTD |= MASKreceiverN; //we alreadi know it's PORTD becuse we are in this interrupt :-)
        
        //stop charge ReceiverN
        PORTD &= ~MASKreceiverN;
      }
    }
  
    _oldbit=_newbit;
  }
}

ISR(PCINT1_vect) {
  if (BCDreceiverN == 1){
    _newbit=PINC;
    _changed=_newbit^_oldbit;
  
    if (_changed & MASKreceiverN){//if PCINTreceiverN has changed
      _time=micros();
      _hasChanged=true;
      
      if (_newbit & MASKreceiverN) { //if PCINTreceiverN now is high
        _startIn[emitterStatus]=_time;
      }else{
        _rawIn[emitterStatus]=_time-_startIn[emitterStatus];
      
        if (!emitterStatus){ //if we read with emitter HIGH and then LOW we have a distace
          rawDistance = _rawIn[0]-_rawIn[1]; //because dark read teorically is lower than light read
        }
      
        //start a new reading changing emitter status
        emitterStatus!=emitterStatus;
        if (emitterStatus){
          switch (BCDemitterP){
            case 0:
              PORTB |= MASKemitterP;
              break;
            case 1:
              PORTC |= MASKemitterP;
              break;
            case 2:
              PORTD |= MASKemitterP;
              break;
          }
        }else{
          switch (BCDemitterP){
            case 0:
              PORTB &= ~MASKemitterP;
              break;
            case 1:
              PORTC &= ~MASKemitterP;
              break;
            case 2:
              PORTD &= ~MASKemitterP;
              break;
          }
        }
    
        //charge ReceiverN using internal pull-up
        PORTC |= MASKreceiverN; //we alreadi know it's PORTC becuse we are in this interrupt :-)
        
        //stop charge ReceiverN
        PORTC &= ~MASKreceiverN;
      }
    }
  
    _oldbit=_newbit;
  }
}

ISR(PCINT0_vect) {
  if (BCDreceiverN == 0){
    _newbit=PINB;
    _changed=_newbit^_oldbit;
  
    if (_changed & MASKreceiverN){//if PCINTreceiverN has changed
      _time=micros();
      _hasChanged=true;
      
      if (_newbit & MASKreceiverN) { //if PCINTreceiverN now is high
        _startIn[emitterStatus]=_time;
      }else{
        _rawIn[emitterStatus]=_time-_startIn[emitterStatus];
      
        if (!emitterStatus){ //if we read with emitter HIGH and then LOW we have a distace
          rawDistance = _rawIn[0]-_rawIn[1]; //because dark read teorically is lower than light read
        }
      
        //start a new reading changing emitter status
        emitterStatus!=emitterStatus;
        if (emitterStatus){
          switch (BCDemitterP){
            case 0:
              PORTB |= MASKemitterP;
              break;
            case 1:
              PORTC |= MASKemitterP;
              break;
            case 2:
              PORTD |= MASKemitterP;
              break;
          }
        }else{
          switch (BCDemitterP){
            case 0:
              PORTB &= ~MASKemitterP;
              break;
            case 1:
              PORTC &= ~MASKemitterP;
              break;
            case 2:
              PORTD &= ~MASKemitterP;
              break;
          }
        }
    
        //charge ReceiverN using internal pull-up
        PORTB |= MASKreceiverN; //we alreadi know it's PORTB becuse we are in this interrupt :-)
        
        //stop charge ReceiverN
        PORTB &= ~MASKreceiverN;
      }
    }
  
    _oldbit=_newbit;
  }
}
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10525
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ERER.h
Code:
#ifndef ERER_h
#define ERER_h

#include "WProgram.h"

class ERER {
  public:
    ERER(byte, byte, byte);
    long getRawDistance();
  private:
    byte getBCDpin(byte);
    void setStatus(byte, byte, boolean);
  };

#endif

attenzione ERER non vuole in input i PIN ma il loro valore PCINT (vedere http://arduino.cc/en/Hacking/PinMapping168)
questo permette di usare sia pin digitali che analogici


ESEMPIO DI UTILIZZO:
con irEmitter digital pin 13 = pcint5
irReceiverN digital 2 = PCINT18
irReceiverP digital 5 = PCINT21

Code:
#inlcude "ERER.h"

ERER lettore = ERER(5, 21, 18);

void setup(){
//non c'è nulla da fare
}

void loop(){
Serial.println( lettore.getRawDistance() );
}

scusate il doppio post ma ho superato il limite di caratteri per post (9500)

EDIT: TODO: funzione di reset e piccolo watch-dog che la richiama. In teoria dovrebbe bastare
Code:
//charge ReceiverN using internal pull-up
  setStatus(BCDreceiverN, MASKreceiverN, true);
  //stop charge ReceiverP
  setStatus(BCDreceiverN, MASKreceiverN, false);
« Last Edit: April 03, 2011, 06:33:07 pm by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Rome
Offline Offline
God Member
*****
Karma: 1
Posts: 993
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Scusa, mi fai capire bene come posso usare questi sorgenti? La "classe" sarebbe una libreria? Come la installo?
Logged

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10525
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

le classi sono programmazione ad oggetti, sono più una struttura che una libreria, poiché contengono sia funzioni che variabili, e vengono usate come una variabile.
Le "installi" come una normale libreria, e le usi come una normale libreria (il file .cpp anche se non menzionato mai viene poi autocaricato)
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Tortona
Offline Offline
God Member
*****
Karma: 2
Posts: 601
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ottimo lavoro! appena posso la provo...
Logged

Se gommo tiene,io vince gara! Se gommo non tiene,io come bomba dentro montagna

Napoli
Offline Offline
Full Member
***
Karma: 0
Posts: 200
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Qualcuno ci darebbe un occhio per piacere? smiley-grin
Logged

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10525
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ottimo lavoro! appena posso la provo...

sarà difficile che funzioni al primo colpo, anche se ad occhio non ci sono errori, salteranno sicuramente fuoi...
Fammi sapere!
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Tortona
Offline Offline
God Member
*****
Karma: 2
Posts: 601
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

il fatto è che ho rotto uno dei led IR che avevo (non chiedermi come smiley-lol) e devo andare in negozio a prenderne un paio...
Logged

Se gommo tiene,io vince gara! Se gommo non tiene,io come bomba dentro montagna

Milan
Offline Offline
Edison Member
*
Karma: 2
Posts: 1128
gioblu.com
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao Lesto ma sei un grande l'hai scritta???  smiley-mr-green smiley-mr-green
La provo subito!! Non sai che piacere!!

Ti farebbe piacere mostrarla su Gioblu.com??
Piu' che altro quasi tutti gli utenti che hanno costruito un robot hanno usato il sistema ERER e tornerebbe PIU CHE UTILE!!
Logged

Community robotica / programmazione Arduino
www.gioblu.com

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10525
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

eheheh l'altra notte avevo voglia di programmare ma i miei progetti non mi attiravano... così mi son messo su questa libreria smiley

Ripeto non è ancora testata e data la sua complessità (si lavora direttamente con i registri) mi  stupirebbe assai se funzionasse al primo  colpo smiley

Se la testate la finiamo per bene, i test da fare sono:
1: prova generale del funzionamento
2: prova con loop() molto cpu intensive
3: prova di più istanze della classe contemporanemente (ovviamente necessita di 2 led per ogni classe)
4: test a lunga durata: non vorrei fosse necessario creare anche un piccolo watchdog, che però può essere utile anche per evitare poche letture troppo distanti ma farne molte vicine (aumentare la frequenza a discapito  della distanza)

piccola domanda: ma visto che reciverP è sempre a LOW, non è meglio collegarlo a GND così si risparmia un PIN?

Infine una volta finita e testata la libreria volevo postarla nel reference con tanto di spiegazione di funzionamento, quindi la metto anche su gioblu.

quello che non mi torna molto è il fatto di chiamare ISR, se si creano più istanze di classe non vorrei che rompesse le balle per funzione già dichiarata...
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Napoli
Offline Offline
Full Member
***
Karma: 0
Posts: 200
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Rispolvero questo topic per capire qual è il codice che devo usare per questi sensori smiley-lol
Logged

0
Offline Offline
Shannon Member
****
Karma: 136
Posts: 10525
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

questa funziona bene, usa gli interrupt ma in maniera tanto semplice da poter essere un esempio per imparare ad usarli

Code:
int ricevitore = 2;
int emettitore = 9;

void setup(){
  Serial.begin(115200);
  pinMode(ricevitore, INPUT);
  pinMode(emettitore, OUTPUT);
  delay(1000);
}

unsigned long ris, lastAlto=0;
boolean statoEmettitore=true;
void loop(){
  //accende e spegne il led emettitore, e ne stampa lo stato
  if (statoEmettitore){
    statoEmettitore=false;
    Serial.print("f ");
  }
  else{
    statoEmettitore=true;
    Serial.print("t ");
  }
  digitalWrite(emettitore, statoEmettitore);

  //legge la durata del segnale HIGH sul ricevitore e la stampa a video
  ris=durataHigh();
  Serial.println( ris );
 
  if (statoEmettitore){
    lastAlto=ris;
  }else{
    if (lastAlto<ris){
      Serial.print( "distanza: " );
      Serial.println( ris-lastAlto );
    }else{
      Serial.println( "lettura incongruente" );
    }
  }
}


//FUNZIONE DI LETTURA BLOCCANTE
//per implementare un time-out basta modificare il while
//non è gestito l'overflow di micro()
unsigned long timeHigh;
volatile unsigned long timeLow;

unsigned long durataHigh(){
  timeHigh=micros();
  timeLow=0;//inizializza la lettura a un valore noto, che fungerà da "tappo" per il while
  digitalWrite(ricevitore, HIGH);//attiva pullUP, per caricare il ricevitore
  attachInterrupt(0, tempoLow, FALLING);//vogliamo intercettare quando il digitalPin2 diverrà LOW ("cade" il segnale da 1 a 0)
  digitalWrite(ricevitore, LOW);//disattiva pullUP, il ricevitore è carico

  //attende che la lettura sia completata
  while ( timeLow==0 )//finchè c'è il valore di tappo (il ricevitore è ancora HIGH)
    ;//non fare niente

  detachInterrupt(0);
  return timeLow-timeHigh;
}

//FUNZIONE DI INTERRUPT
//più minimale di così non mi viene :-)
void tempoLow(){
  timeLow=micros();
}
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Napoli
Offline Offline
Full Member
***
Karma: 0
Posts: 200
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie!
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi son letto tutto il topic e vorrei capire:
Quindi la libreria non è stata realizzata alla fine?
Lesto confermi che l'ultimo codice che hai postato è quello "definitivo"?
MA soprattutto, anche se un po' OT,sono su Ubuntu e lo stavo provando, ma nel serial monitor leggo solo caratteri strani, c'e' qualche impostazione da dargli per la codifica? la versione dell'IDE è la 0022Ubuntu0.1
Grazie!
Logged

Pages: 1 ... 9 10 [11] 12   Go Up
Jump to: