Go Down

Topic: PING))) Per Arduino (Read 1 time) previous topic - next topic

Ualone

Oct 31, 2007, 06:37 pm Last Edit: Nov 01, 2007, 04:02 pm by Ualone Reason: 1
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).
I Pwn you in C/C++,HTML,SQL,Assembly.

Ualone

#1
Oct 31, 2007, 06:38 pm Last Edit: Nov 01, 2007, 04:17 pm by Ualone Reason: 1
EDIT: Programma corretto e riscritto.

Code: [Select]

/*
  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);
 }
}

I Pwn you in C/C++,HTML,SQL,Assembly.

alyver00

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

Ualone

#3
Nov 05, 2007, 05:44 pm Last Edit: Nov 05, 2007, 10:48 pm by Ualone Reason: 1
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  :'(

EDIT: Problema risolto (chi cavolo pensava fosse il cavo), sto testando le varie funzioni... ti faccio sapere
I Pwn you in C/C++,HTML,SQL,Assembly.

Ualone

La funzione Freqout non va :/
Suggerimenti, consigli? (Chissà a chi li chiedo, sembra che la sezione italiana di arduino sia la più desolata :|)
I Pwn you in C/C++,HTML,SQL,Assembly.

admin

#5
Nov 05, 2007, 08:57 pm Last Edit: Nov 05, 2007, 09:00 pm by admin Reason: 1

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

alyver00

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.

alyver00

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.

Ualone

#8
Nov 05, 2007, 10:42 pm Last Edit: Nov 05, 2007, 11:15 pm by Ualone Reason: 1
beh si a me serve l'onda per inviare frequenze dagli infrarossi

Quote
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.

Quote
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 è :/
Ma sbaglio o Arduino ha già una funzione pulseIn di suo? Cosa restituisce tale funzione?

Quote
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.
I Pwn you in C/C++,HTML,SQL,Assembly.

Ualone

Ah alyver grazie di avermi fatto notatare i 3 if di fila èstata una piccola distrazione
I Pwn you in C/C++,HTML,SQL,Assembly.

alyver00

Quote
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 è :/
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]

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! >:(

Ualone

#11
Nov 06, 2007, 01:48 pm Last Edit: Nov 06, 2007, 07:27 pm by Ualone Reason: 1
Quote
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 :P solo alla maggiorparte  ;)
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!

Code: [Select]
/*
  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 :/
I Pwn you in C/C++,HTML,SQL,Assembly.

Ualone

#12
Nov 06, 2007, 06:53 pm Last Edit: Nov 06, 2007, 06:58 pm by Ualone Reason: 1
ecco la funzione modificata

Code: [Select]

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);
 }
}
I Pwn you in C/C++,HTML,SQL,Assembly.

alyver00

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
Code: [Select]
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)

Go Up