PING))) Per Arduino

Salve a tutti,
Mi chiamo Federico, sono uno studente dell'ITIS Marconi di Latina sezione robotica, mi sono da poco appassionato a arduino visto anche il fatto che si programma in C (linguaggio che conosco molto bene) ho così deciso di convertire il programma PING))) della parallax che utilizza 2 rilevatori IR e un sensore "Ping" costituito da 2 RX/TX ad Ultrasuoni.
Vi posto il programma, visto che ho qualche dubbio sulla funzione che rileva la distanza (Pulsin) magari datemi qualche consiglio.
Il prblema principale è che la funzione pulsin mi restituisce un risultato, ma devo trovare un modo per convertire quel numero nella distanza effettiva (cm o mm).

EDIT: Programma corretto e riscritto.

/* 
   Nome: PING))) Adattato per Arduino
   Autore: Zappone Federico
   Data: 31-10-2007
*/

#define Piezo 2
#define RightServo 3
#define LeftServo 4
#define PingServo 5
#define RightIR 6
#define LeftIR 7
#define RightIRR 9
#define LeftIRR 10
#define Ping 11

//Dichiarazione Variabili
int task;
int IR1,IR2;
int counter=0;
long distance;
long olddistance;

//Funzioni di movimento
void Move_Foward();
void Turn_Right();
void Turn_Left();
void Back_Up();
//Funzioni PING)))
void Ping_Out();
void Ping_Around();
//Imitazione funzioni parallax
void Pulsout(int Pin,int Period);
void Pulsin(int Pin, int State, int &Time);
void Freqout(int Pin, int Period, int Freq);

void setup()
{
  //Setup dei pin
  pinMode(Piezo,OUTPUT);
  pinMode(RightServo,OUTPUT);
  pinMode(LeftServo,OUTPUT);
  pinMode(PingServo,OUTPUT);
  pinMode(RightIR,OUTPUT);
  pinMode(LeftIR,OUTPUT);
  pinMode(RightIRR,INPUT);
  pinMode(LeftIRR,INPUT);
}


void loop()
{
  // Beep del piezo all'inizio
  Freqout(Piezo,2000,3000);
  //Ciclo principare
  while(1)
  {
    Freqout(LeftIR,1,38500);
    IR1=digitalRead(LeftIRR);
    Freqout(RightIR,1,38500);
    IR2=digitalRead(RightIRR);
    
    if(IR1==0 && IR2==0) //Ostacolo davanti
    {
      Ping_Around(); //Pinga
    }
    if(IR1==0) //A sinistra
    {
      Ping_Around(); //Pinga
    }
    if(IR2==0) //A destra
    {
      Ping_Around(); //Pinga
    }
  
    counter++; //Conta le pulsazioni del servo
  
    if(counter>10) //Dopo 10 pulsazione del servo pinga
    {
      Ping_Out();
    }
  
    if(distance>30) //Ostacolo più distante di 30 cm?
    {
      Move_Foward(); //Vai avanti
    }
    else
    {
      Ping_Around(); //Altrimenti pinga
    }
  }
}

void Move_Foward()
{
  Pulsout(PingServo,750);
  Pulsout(LeftServo,850);
  Pulsout(RightServo,650);
}

void Turn_Left()
{
  for(int i=0;i<7;i++)
  {
    Pulsout(PingServo,750);
    Pulsout(LeftServo,650);
    Pulsout(RightServo,650);
    delay(20);
  }
}

void Turn_Right()
{
  for(int i=0;i<7;i++)
  {
    Pulsout(PingServo,750);
    Pulsout(LeftServo,850);
    Pulsout(RightServo,850);
    delay(20);
   } 
}

void Back_Up()
{
  for(int i=0;i<40;i++)
  {
    Pulsout(PingServo,750);
    Pulsout(LeftServo,650);
    Pulsout(RightServo,850);
    delay(20);
  }
}

void Ping_Out()
{
  counter=0;
  pinMode(Ping,OUTPUT);
  digitalWrite(Ping,LOW);
  Pulsout(Ping,5);
  pinMode(Ping,INPUT);
  Pulsin(Ping,1,distance);
}

void Ping_Around()
{
  counter=0;
  olddistance=30;
  /*
  Il Sensore Ping non serve a rilevare gli ostacoli (per quello ci sono gli infrarossi) ma a conoscere
  la posizione dove c'è più spazio e per stabilirlo pinga in 4 direzioni diverse
  */
  for(int i=0;i<20;i++) //Pinga 90° a sinistra
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,1085);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    Pulsin(Ping,1,distance);
    delay(20);
  }
  if(distance>olddistance)
  {
    olddistance=distance;
    task=1;
  }

  for(int i=0;i<20;i++) //Pinga 45° a sinistra
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,850);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    Pulsin(Ping,1,distance);
    delay(20);
  }
  if(distance>olddistance)
  {
    olddistance=distance; 
    task=2;
  }
  
  for(int i=0;i<20;i++) //Pinga 45° a destra
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,400);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    Pulsin(Ping,1,distance);
    delay(20);
  }
  if(distance>olddistance)
  {
    olddistance=distance;
    task=3;
  }
  
  for(int i=0;i<20;i++) //Pinga 90° a destra
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,20);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    Pulsin(Ping,1,distance);
    delay(20);
  }
  if(distance>olddistance)
  {
    olddistance=distance;
    task=4;
  }
  
  switch(task)
  {
    case 1:
      Turn_Right();
      Turn_Right();
      Turn_Right();
      Turn_Right();
    break;
    
    case 2:
      Turn_Left();
      Turn_Left();
    break;
    
    case 3:
      Turn_Right();
     break;
     
     case 4:
       Turn_Right();
       Turn_Right();
     break;
  }

}

//--------------------------- Funzioni Parallax Riscritte ------------------------------------------

void Pulsout( int Pin, int Period)
{
  digitalWrite(Pin, HIGH);
  delayMicroseconds(Period);
  digitalWrite(Pin, LOW);
  delay(20);
}

void Pulsin(int Pin, int State, long &Time) //State può essere 1 o 0 per HIGHT o LOW
{
  int val;
  val = digitalRead(Pin);
  switch(State)
  {
    case 1:
      while(val == LOW)
      {
        val = digitalRead(Pin);
      }
      while(val == HIGH)
      {
        val = digitalRead(Pin);
        Time++;
      }
    break;

    case 0:
      while(val == HIGH)
      {
        val = digitalRead(Pin);
      }
      while(val == LOW)
      {
        val = digitalRead(Pin);
        Time++;
      }
    break;
  }
}

void Freqout(int Pin, int Period, int Freq)
{
  int hperiod;
  long cycles;

  hperiod = (500000 / Freq) - 7;
  cycles = ((long)Freq * (long)Period) / 1000;

  for (long i=0; i<= cycles; i++)
  {
    digitalWrite(Pin, HIGH);
    delayMicroseconds(hperiod);
    digitalWrite(Pin, LOW);
    delayMicroseconds(hperiod - 1);
  }
}

Ciao, gli ho dato un occhiata rapida, ma prima di dirti cosa penso volevo chiederti se con questo codice ti funziona,rileva gli ostacoli?

Ciao
oggi è finalmente arrivata la mia scheda, provo a installarla ma alla fine dell'installazione dei driver appare: Codice 10 impossibile avviare la periferica, di conseguenza non sono ancora riuscito a testare il programma.
ps: ho provato a cercare nel forum per una soluzione ma non trovo nulla, ogni aiuto è gradito :cry:

EDIT: Problema risolto (chi cavolo pensava fosse il cavo), sto testando le varie funzioni... ti faccio sapere

La funzione Freqout non va :confused:
Suggerimenti, consigli? (Chissà a chi li chiedo, sembra che la sezione italiana di arduino sia la più desolata :|)

in che senso non funziona?

considera che c'è un interrupt ogni millisecondo percui ti frega i timing

la sezione italiana è desolata perche l'italia è sempre indietro di cent'anni
e pensare che le facciamo qui..

massimo

Se è giusto quello che ho capito del tuo programma, la freqout ti permette di scrivere sul pin che ti interessa un "onda" quadra della frequenza e del tempo stabilito che ti interessa,se questo che ho capito è esatto allora non ci siamo molto con i valori dell'hperiod(non capisco assolutamente da dove viene fuori quel 500000) e dei cycles.
Se devi fare quello che ho capito io to serve una formula che dovresti saperla già: f = 1/T con frequenza e T il periodo (o ciclo per capirci in un clock la durata in tempo tra due fronti di salita).
con questa ti tiri fuori il tempo di un cliclo, lo dividi per 2 e ottieni il tempo del delay tra la scrittura di uno stato di uscita del pin. fai ciclare tutto per il "periodo" che gli passi alla funzione diviso per il peridodo dell'onda (T).
spero di essere d'aiuto.
un altro suggerimento: se non lo hai fatto di tua spontanea volontà stai attento nel loop() quando usi i primi tre if, se lo hai fatto perchè Ping_Around() possa essere eseguito 3 volte se IR1 e IR2 sono uguali a zero va bene, ma se devi escludere i casi ( entrambi zero, o uno solo dei due a zero) usa "else" altrimenti esegui cose che non vorresti.
spero di essere stato d'aiuto almeno in qualcosa.

io avevo fatto una "tesina" per l'esame di maturità su un circuito misuratore di distanze a ultrasuoni, per calcolare la distanza l'unica cosa da fare è mandare un treno d'impulsi, far partire un timer,aspettare di ricevere gli impulsi nel ricevitore, e salvare il tempo impiegato. Sapendo che in aria il suono si propaga a 330m/s, dividi il tempo salvato per il tempo di propagazione(330m/s attento alle unità di misura),lo dividi per 2 ancora, e ottieni la distanza tra il sensore e l'oggetto.
Se tutto questo già lo sapevi, mi spiace di non essere stato di ulteriore aiuto.

beh si a me serve l'onda per inviare frequenze dagli infrarossi

considera che c'è un interrupt ogni millisecondo percui ti frega i timing

già lo so purtroppo, comunque a me serve poter inviare una frequenza di 38,5 khz il più precisa possibile.

io avevo fatto una "tesina" per l'esame di maturità su un circuito misuratore di distanze a ultrasuoni, per calcolare la distanza l'unica cosa da fare è mandare un treno d'impulsi, far partire un timer,aspettare di ricevere gli impulsi nel ricevitore, e salvare il tempo impiegato. Sapendo che in aria il suono si propaga a 330m/s, dividi il tempo salvato per il tempo di propagazione(330m/s attento alle unità di misura),lo dividi per 2 ancora, e ottieni la distanza tra il sensore e l'oggetto.
Se tutto questo già lo sapevi, mi spiace di non essere stato di ulteriore aiuto.

infatti se vedi la funzione Pulsin, conta fino a quando non arriva l'impulso, ora bisogna sapere in un secondo quante volte si incrementa quel contatore di sicuro non 20M perchè ci sono gli interrupt e altra roba, quindi non so di preciso quanto è :confused:
Ma sbaglio o Arduino ha già una funzione pulseIn di suo? Cosa restituisce tale funzione?

la sezione italiana è desolata perche l'italia è sempre indietro di cent'anni
e pensare che le facciamo qui..

quoto... mi aggiravo per il forum e vedevo che i progetti degli italiani si limitano a led che si accendono in serie... che squallore, una scheda con queste potenzialità sprecata per giochi di luce.

Ah alyver grazie di avermi fatto notatare i 3 if di fila èstata una piccola distrazione

infatti se vedi la funzione Pulsin, conta fino a quando non arriva l'impulso, ora bisogna sapere in un secondo quante volte si incrementa quel contatore di sicuro non 20M perchè ci sono gli interrupt e altra roba, quindi non so di preciso quanto è :confused:
Ma sbaglio o Arduino ha già una funzione pulseIn di suo? Cosa restituisce tale funzione?

hai due modi per calcolare il tempo, o utilizzando millis() (salvi il valore poco prima di inviare l'impulso, e una volta arrivato l'impulso lo ricontrolli) oppure come hai detto tu con pulseIn(), restituisce la durata in microsecondi di quanto tampo un pin è rimasto al valore "value" che gli hai passato alla pulseIn(), se te mandi un impulso "alto" dovresti usare pulseIn(n_pin_entrata,LOW); la funzione attende e tiene conto del tempo che passa da quando il pin è passato a LOW(nel caso tuo subito dopo aver mandato l'impulso) a quando arriva HIGH, cioè quando è arrivato il tuo impulso, restituisce il tempo in microsecondi.e ricordati che è una funzione bloccante.[/quote]

quoto... mi aggiravo per il forum e vedevo che i progetti degli italiani si limitano a led che si accendono in serie... che squallore, una scheda con queste potenzialità sprecata per giochi di luce.

grazie per la considerazione, io sto sperimentando arduino come dispositivo per leggere onde cerebrali, sono fermo ultimamente perchè mi sono spostato da arduino come tramite tra cervello e computer, alla progettazione di una "scheda audio" che acquisisce le onde, le modula in am e le trasferisce alla scheda audio del pc.valuto la funzionalità di questa scheda e dopo passo alla costruizione dello shield per arduino per l'eeg. gli italiani non sono tutti uguali! >:(

grazie per la considerazione, io sto sperimentando arduino come dispositivo per leggere onde cerebrali, sono fermo ultimamente perchè mi sono spostato da arduino come tramite tra cervello e computer, alla progettazione di una "scheda audio" che acquisisce le onde, le modula in am e le trasferisce alla scheda audio del pc.valuto la funzionalità di questa scheda e dopo passo alla costruizione dello shield per arduino per l'eeg. gli italiani non sono tutti uguali!

E' naturale che non mi riferisco a tutti gli italiani :stuck_out_tongue: solo alla maggiorparte :wink:
Grazie per la spiegazione, presto posto il codice modificato.

Riguardo la frequenza, a me serve semplicemente una funzione che ha come parametri:
Pin
Tempo di durata (ms)
Frequenza (hertz)
e mi genera la frequenza data per il tempo deciso su un determinato pin.

EDIT: Finito!

/* 
   Nome: PING))) Adattato per Arduino
   Autore: Federico Zappone
   Data: 6-11-2007
*/

#define Piezo 2
#define RightServo 3
#define LeftServo 4
#define PingServo 5
#define RightIR 6
#define LeftIR 7
#define RightIRR 9
#define LeftIRR 10
#define Ping 11

int task;
int IR1,IR2;
int counter=0;
float distance;
float olddistance;

void Move_Foward();
void Turn_Right();
void Turn_Left();
void Back_Up();
void Ping_Out();
void Ping_Around();
void Pulsout(int Pin,int Period);
void Pulsin(int Pin, int State, float &Time);
void Freqout(int Pin, int Period, int Freq);

void setup()
{
  pinMode(Piezo,OUTPUT);
  pinMode(RightServo,OUTPUT);
  pinMode(LeftServo,OUTPUT);
  pinMode(PingServo,OUTPUT);
  pinMode(RightIR,OUTPUT);
  pinMode(LeftIR,OUTPUT);
  pinMode(RightIRR,INPUT);
  pinMode(LeftIRR,INPUT);
}

void loop()
{
  Freqout(Piezo,2000,3000);
  while(1)
  {
    Freqout(LeftIR,1,38500);
    IR1=digitalRead(LeftIRR);
    Freqout(RightIR,1,38500);
    IR2=digitalRead(RightIRR);
    
    if(IR1==0 && IR2==0)
    {
      Ping_Around();
    }
    else if(IR1==0)
    {
      Ping_Around();
    }
    else if(IR2==0)
    {
      Ping_Around();
    }
  
    counter++;
  
    if(counter>10)
    {
      Ping_Out();
    }
  
    if(distance>30)
    {
      Move_Foward();
    }
    else
    {
      Ping_Around();
    }
  }
}

void Move_Foward()
{
  Pulsout(PingServo,750);
  Pulsout(LeftServo,850);
  Pulsout(RightServo,650);
}

void Turn_Left()
{
  for(int i=0;i<7;i++)
  {
    Pulsout(PingServo,750);
    Pulsout(LeftServo,650);
    Pulsout(RightServo,650);
    delay(20);
  }
}

void Turn_Right()
{
  for(int i=0;i<7;i++)
  {
    Pulsout(PingServo,750);
    Pulsout(LeftServo,850);
    Pulsout(RightServo,850);
    delay(20);
   } 
}

void Back_Up()
{
  for(int i=0;i<40;i++)
  {
    Pulsout(PingServo,750);
    Pulsout(LeftServo,650);
    Pulsout(RightServo,850);
    delay(20);
  }
}

void Ping_Out()
{
  counter=0;
  pinMode(Ping,OUTPUT);
  digitalWrite(Ping,LOW);
  Pulsout(Ping,5);
  pinMode(Ping,INPUT);
  distance=pulseIn(Ping,LOW);
  distance=(distance/100000) * 330000;
}

void Ping_Around()
{
  counter=0;
  olddistance=30;
  task=0;

  for(int i=0;i<20;i++)
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,1085);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    distance=pulseIn(Ping,LOW);
    delay(20);
  }

  distance=(distance/100000) * 330000;

  if(distance>olddistance)
  {
    olddistance=distance;
    task=1;
  }

  for(int i=0;i<20;i++)
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,850);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    distance=pulseIn(Ping,LOW);
    delay(20);
  }

  distance=(distance/100000) * 330000;

  if(distance>olddistance)
  {
    olddistance=distance;
    task=2;
  }
  
  for(int i=0;i<20;i++)
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,400);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    distance=pulseIn(Ping,LOW);
    delay(20);
  }
  
  distance=(distance/100000) * 330000;

  if(distance>olddistance)
  {
    olddistance=distance;
    task=3;
  }
  
  for(int i=0;i<20;i++)
  {
    pinMode(Ping,OUTPUT);
    Pulsout(PingServo,20);
    Pulsout(Ping,5);
    pinMode(Ping,INPUT);
    distance=pulseIn(Ping,LOW);
    delay(20);
  }

  distance=(distance/100000) * 330000;

  if(distance>olddistance)
  {
    olddistance=distance;
    task=4;
  }
  
  switch(task)
  {
    case 0:
      Turn_Right();
      Turn_Right();
      Turn_Right();
      Turn_Right();
    break;
    
    case 1:
      Turn_Left();
      Turn_Left();
    break;

    case 2:
      Turn_Left();
    break;
    
    case 3:
      Turn_Right();
    break;
     
     case 4:
       Turn_Right();
       Turn_Right();
     break;
  }

}

void Pulsout(int Pin, int Period)
{
  digitalWrite(Pin, HIGH);
  delayMicroseconds(Period);
  digitalWrite(Pin, LOW);
  delay(20);
}

void Freqout(int Pin, int Period, int Freq)
{
  
  int hperiod = (100000/Freq)/2;
  int cycles = (Period/hperiod)/2;
  
  for (int i=0;i<cycles;i++)
  {
    digitalWrite(LED, HIGH);
    delayMicroseconds(hperiod);
    digitalWrite(LED, LOW);
    delayMicroseconds(hperiod);
  }
}

solo che la funzione freqout attuale non va con le frequenze dispari, ne avevo scritta un altra con hperiod float e poi per calcolare i cycles faceva il cast, ma il tempo è sballato :confused:

ecco la funzione modificata

void Freqout(int Pin, int Period, int Freq)
{
  float app;
  float hperiod = (1000/Freq)/2;
  app = (Period/hperiod)/2;
  int cycles = (int) app;
  
  for (int i=0;i<cycles;i++)
  {
    digitalWrite(Pin, HIGH);
    delay(hperiod);
    digitalWrite(Pin, LOW);
    delay(hperiod);
  }
}

allora è giusta la funzione, hai l'errore di utilizzare delay al posto di delaymicroseconds() ti spiego: se dividi 1000/freq ottieni un tempo in millisecondi( e fin quà tutto ok per delay) il problema sta nel fatto che te hai freq alte di circa 38000 Hz, usandole come divisore avrai 0,0etcetc che probabilmente delay() non comprende appieno,prova a fare

float hperiod = (1000000/Freq)/2;
...
...
for(...)
...
delayMicroseconds(hperiod);
...

forse già qualcosa cambia.
sai che con questo ciclo for non avrai mai il tempo una frequenza della durata Period che vuoi tu, ma penso che cambi propio di poco.
(scusa se non sono molto rapido a rispondere ma sono in spagna e mi è difficile trovare una postazione internet)