CRONOGRAFO BALISTICO

Ho provato a buttare giu uno schizzo, fa un po pena perche' Eagle non e' un cad grafico, ma dovrebbe servire a spiegare almeno a grandi linee cosa intendevo ...

il tubo dovrebbe avere almeno tre diversi diametri all'interno, cosa non facile se non si ha un tornio, ma probabilmente si puo realizzare qualcosa di simile incollando tre pezzi di tubo uno dentro l'altro ... la prima variazione di diametro la si userebbe come battuta sul piano di volata, per garantire l'allineamento, insieme alla lunghezza della parte che calza sopra lo stabilizzatore ... il secondo gradino si potrebbe anche ignorare se non si mette il dischetto forato, che insieme ai fori laterali serve solo per scaricare il piu possibile i residui prima che raggiungano la zona dei sensori, aumentandone la durata, o comunque riducendo lo sporco che si accumulera' con il tempo ... laser e fotodiodi dovrebbero affacciarsi all'interno del tubo attraverso forellini da un paio di mm, perpendicolari all'asse della canna, in modo che il pallino interrompa il raggio per forza, anche con un diametro della parte terminale del tubo di 10 o piu mm ... non dovrebbe essere troppo difficile realizzarlo, avendo l'accesso a qualche strumento di lavoro (potendo utilizzare frese o CNC, potrebbe anche non essere un tubo ma un quadrato o un'esagono o quello che si trova in cui realizzare il foro principale a piu diametri ed i fori laterali, risulterebbe anche piu robusto, ma senza CNC o fresa, bisogna ripiegare sui tubi)

I fotodiodi andrebbero protetti esternamente una volta posizionati, per evitare che luce esterna li influenzi ... bisognerebbe anche testare il materiale dei tubi per essere sicuri che sia opaco alla lunghezza d'onda del laser (lo dico perche' una volta mi e' successo, avevo realizzato un sensore per diverse lunghezze d'onda, dagli UV agli IR, e l'avevo messo in una di quelle scatole grigie della Gewiss, ma il sensore degli IR dava sempre dati assurdi, poi provando ho scoperto che anche se la plastica era opaca al visibile ed all'UV, lasciava invece passare gli IR come se fosse stato vetro sabbiato :stuck_out_tongue: :D)

Bgiorno a tutti,

dunque ritorno alla carica per portare avanti qualche tentativo grazie anche alle utili informazioni fornite nel thread. Ho una manciata di fotodiodi, diodi ir e normali. Vorrei fare qualche prova pratica sia sul codice sia sul funzionamento del rilevatore di velocità.
Il codice è quello di cui al post #1 che riporto di seguito per comodità. Lo sto studiando ma, vista la mia ancora scarsa preparazione a riguardo vi chiedo gentilmente di fornirmi un vostro parere.
Pr la parte hardware cme detto al momento ho solo diodi e fotodiodi...sono questi in in grado ri rilevare velocità di 160/170 metri x secondo?

/*
Tomado de http://aeroquad.com/showthread.php?845-How-do-I-make-a-tachometer-with-my-spare-arduino-board-and-IR-LED-and-RECEIVER
Modificado por Pablo Andrade Mejía http://www.arduinolab.wordpress.com

05 de Noviembre de 2012

Se le añadió la función de enviar la velocidad en metros por segundo y pies por segundo al monitor serial
lo que quita la necesidad de tener una pantalla de cristal líquido

Aquellos que tengan dudas acerca de cómo se debe conectar los sensores para que funcione correctamente
hagan click aquí http://www.instructables.com/id/Arduino-Based-Optical-Tachometer/step3/IR-Detector-Circuit/

Los fotodiodos o fototransistores son nombrados como attachInterrupt(0, front, CHANGE); Éste está relacionado
con el pin digital 2, y, el attachInterrupt(1, rear, CHANGE); Éste está relacionado con el pin digital 3

Quienes quieran probarlo pueden conectar dos botones a los pines 2 y 3

Los fotodiodos deben tener una resistencia entre 10k y 100kohm conectados al colector (pin, o pata larga) y esta al pin digital
para asegurarnos que cuando el haz de luz sea interrumpido el voltaje llegue a 0 o tierra
*/

#include <LiquidCrystal.h>
 
#define MPS2FPSCOEFF 3.28084
#define LENGTH 0.159             
#define MICRO2SEKCOEFF 1000000

LiquidCrystal lcd(4, 5, 6, 7, 8, 9);

volatile int stateFront = HIGH;
volatile int stateRear = HIGH;

int led1 = 12;                             
int led2 = 13;                             
int startChrono;
unsigned long startTime, stopTime, elapsed;
double fpsSpeed, mpsSpeed; //double tiene la misma función que float, así que no hay que preocuparse
 
void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Super Chrono");
  Serial.print("Cronografo");
  lcd.setCursor(0, 1);
  lcd.print("by Honk");
  delay(700);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Initializing...");
  Serial.println("Inicializando"); 
  delay(700);
  lcd.clear();
 
  startChrono = 0;
  elapsed = 0;
  fpsSpeed = mpsSpeed = 0;
 
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  /*
  Sí los resultados no son los esperados donde dice CHANGE cambien por RISING o LOW
  tanto como en attachInterrupt(0, front, "      "); como en attachInterrup(1, rear, "     ");
 
  Sí todo resulta bien simplemente no hagan nada
  */
  attachInterrupt(0, front, CHANGE); //0 (on digital pin 2) kanske falling/rising/low
  attachInterrupt(1, rear, CHANGE);  //1 (on digital pin 3)
 
  lcd.setCursor(0, 0);
  lcd.print("Take a shot!");
  Serial.println("Preparado para disparar?");
}
 
void loop()
{
  //Start counting when interrupted
  if(stateFront == LOW && startChrono == 0)
  {
    startTime = micros();  // Count microseconds since start
    startChrono = 1;       // Set Chrono flag
    digitalWrite(led1, HIGH);
  }
 
  // Stop counting and calculate speed
  if(stateRear == LOW && startChrono == 1)
  {
    stopTime = micros();  // Count microseconds since start
    startChrono = 0;      // Clear Chrono flag
    elapsed = stopTime - startTime;  // Calculate elapsed time (in us)
 
    digitalWrite(led2, HIGH);
    mpsSpeed = (LENGTH*(MICRO2SEKCOEFF)) / elapsed;            // s = v * t, v = s / t
    fpsSpeed = mpsSpeed * MPS2FPSCOEFF;

    lcd.clear();
    lcd.print("Fps: ");
    lcd.print(fpsSpeed);
    Serial.println("PPS(Pies por segundo) ");
    Serial.print(fpsSpeed);
    lcd.setCursor(0, 1);
    lcd.print("m/s: ");
    lcd.print(mpsSpeed);
    Serial.println("Metros por segundo ");
    Serial.print(mpsSpeed);
   
    startChrono = 0;
   
    delay(500);
    digitalWrite(led2, LOW);
    digitalWrite(led1, LOW); 
   
  }
 
}

void front()
{
  stateFront = !stateFront;
}

void rear()
{
  stateRear = !stateRear;
}

vince59:
... fotodiodi...sono questi in in grado ri rilevare velocità di 160/170 metri x secondo?
...

Dipende da che fotodiodi sono, se ci dai la sigla ti diamo informazioni piu precise ...

Comunque, indicativamente, i normali fotodiodi (moderni) hanno un tempo di risposta intorno agli 0.5 microsecondi, alcuni necessitano di 1uS ... i fotodiodi PIN sono in genere intorno ai 5/8 nanosecondi (ma alcuni modelli arrivano a 2nS) ... il pallino e' lungo in genere dai 4 ai 6 mm, secondo i modelli, consideriamo il caso peggiore di 4mm ed 1uS ... 170m/S sono 170mm per millisecondo, o 0.17mm (170 millesimi di mm) ogni microsecondo ... un pallino lungo 4mm che passa davanti ad un diodo a 170m/s, se non ho sbagliato a calcolare, lo dovrebbe oscurare per almeno 23 microsecondi, quindi in teoria piu che sufficenti per far scattare anche fotodiodi di tipo vecchio, che avevano in media da 5 a 20 microsecondi di tempo di risposta ...

Se poi i tuoi sono fotodiodi PIN da 5nS, il problema non si pone neppure ... intanto che il pallino gli transita davanti, non solo lo rilevano, ma fanno in tempo anche a scendere al bar a far colazione e rientrare prima che abbia finito di passare :smiley:

...e sono di nuovo qui. Devo riuscire a fare anche sto "coso"...

Vorrei utilizzare questi

oppure farlo con due testine laser (link) e cercare di realizzare una barriera zigzag con gli specchi

https://www.ebay.it/itm/A75-LASER-650nm-5mW-6MM-PUNTATORE-ROSSO-ARDUINO-3V-diodo/232728144012?hash=item362fada88c:g:4AwAAOSwdPtay35F

guarda QUI che bello già pronto e fatto :smiley:

scherzo ovviamente, seguo con interesse perchè l'argomento mi interessa.
anch'io ho una 977 ma quelle sopra i 7.5J :slight_smile:

vince59:
...
oppure farlo con due testine laser (link) e cercare di realizzare una barriera zigzag con gli specchi
...

Se parli di quello da fissare sulla canna, la barriera a zig-zag non serve, basta usare dei normali fotodiodi e mettere sia il led che il fotodiodo in cavita' che si affacciano verso l'interno tramite dei forellini da 2.5 / 3 mm allineati con l'asse della canna ... il pallino interrompera' per forza i raggi, in quelle condizioni, perche' sono vincolati alla canna e piu stretti del pallino stesso ... :wink:

@ gianlucaf ...che gusto c'è a comprarlo già fatto? La 977 è bellissima ....sono tentato di fare un upgrade :smiling_imp: :smiling_imp: :smiling_imp: :smiling_imp: :smiling_imp:

@ etemenanki. Dunque sto smanettando ora con diodi IR e relativi ricevitori TSOP 34838 ma mi sembrano lenti nelle risposta. Ho fatto delle prove moooolto elementari sulla basetta millefori ma mi sembra che l'interruzione del fascio IR da parte di un oggetto molto piccolo e molto veloce non venga rilevata.
Ho ordinato nel frattempo laser e riceventi. Concordo che a questo punto ne bastano due messi in un tubo allineato longitudinalmenmte con la canna. Il piombino di sicuro interromperà il fascio.
Leggendo i tuoi post ho compreso che la risposta del ricevitore deve essere molto veloce - sto studiando - ma non mi è chiaro se il TSOP 34838 essendo un diodo PIN anche se a IR possa andare bene come caratteristiche.
In attesa di ricevere il materiale voglio provare a mettera a punto il codice e provare con gli IR.
Consigli ben accetti.

Ehm, no, la serie TSOP sono moduli ricevitori, non hanno nulla a che fare con i diodi pin (hanno piu o meno la stessa proporzione di velocita' che c'e' fra una lamborghini ed una ford "model A" :D)

Ora sto uscendo, oggi te ne cerco qualcuno sui datasheet, di diodi PIN o fotodiodi veloci "veri" :wink:

Guglielmo, aiutami sennò spacco il PC co na capocciata!!!!

Sono due giorni che sbatto la capoccia co sti caxxo di interrupt ma non riesco proprio a capire come lavorarci per creare il codice. Potresti, come hai già fatto per i millis, guidarmi un pò per come impostare il codice e soprattutto com egestire gli interrupts?

BPV10NF ... TEFD4300F ... SFH229FA ... QSD2030F ... I piu comuni che mi sono capitati a tiro, non SMD, dovrebbero essere tutti sotto l'euro l'uno ... questi sono PIN, quindi veloci, tempi di risposta medi 10nS ... SFH229FA e TEFD4300F sono da 3mm di diametro, quindi anche poco ingombranti ...

I TSOP essendo ricevitori per telecomandi, contengono anche l'AGC e l'elettronica di decodifica a volte, e sono progettati per frequenza di modulazione di 38KHz ... il loro diodo viaggia a microsecondi, a volte anche millisecondi , non si possono usare come normali diodi per applicazioni veloci ... ovviamente per leggere i normali fotodiodi devi fargli un minimo di circuito, ma e' una cosa piuttosto semplice da fare ...

Grazie Etemenanki,
prima o poi li trovo ora sono fuori roma con difficoltà logistiche.
Sto cominciando a ragionare sul codice ma non mi entrano in testa questi interrupts. Hoscaricato qualche esempio e sto provando a studiare.
Vorrei abbozzare l'ahardware ed il codice.
Per l'HW non ho problemi mi sembra di capire che:

  • i diodi IR vadano semplicemente alimetati mediante resistenza (già sto smanettando con gli IR ed i TSOP);
  • i diodi PIN (in packag T1) come andranno cablati?..immagino sui pin D2 e D3 visto che sono gli unici che lavorano con gli interrupt. Giusto? ...se si con quale polarizzazione?
    Per il codice cerco di arrivarci da solo...

Diodi IR: resistenza in serie, se usi i 5V di arduino, 680 ohm dovrebbero essere sufficenti (sono vicini ai fotodiodi e non devono servire come illuminatori, quindi dargli pochi mA dovrebbe bastare, al massimo si abbassano le resistenze a 470 ohm se si vede che non basta la corrente)

Fotodiodi: di solito si usano gli operazionali, ma anche un semplice paio di transistor BC337 dovrebbe bastare per un'applicazione simile ... tecnicamente, sarebbe possibile anche farne a meno ed usare un semplice paio di resistenze da 22K o valori simili, collegandoli polarizzati inversamente (catodi dei diodi al +5V, anodi ai pin di arduino, resistenze fra i pin e massa come pull-down e per polarizare inversamente il diodo), dato che gli ingressi di arduino sono ad alta impedenza, quindi anche l'uscita diretta del fotodiodo in teoria dovrebbe bastare a fargli cambiare stato ... e' comunque da provare, se non basta, si mettono anche i transistor ...

Nel fare i test, occhio che gli IR presenti nell'ambiente possono falsarti facilmente le letture ... usa dei tubetti di cartoncino o metallo (non plastica, a meno che tu non sia sicuro che e' opaca agli IR, perche' molte plastiche che alla luce visibile risultano nere o comunque opache, sono trasparenti o lasciano passare quasi tutta la banda IR) per schermare completamente i fotodiodi, anche dietro (senza mandarli in corto se usi il metallo) ... per lo stesso motivo, poi, il tubo finale andrebbe costruito in metallo, alluminio, ottone, quello che trovi piu facile da lavorare, e non in plastica, sempre se non hai plastica che sei sicuro sia completamente opaca agli IR ...

vince59:
Guglielmo, aiutami sennò spacco il PC co na capocciata!!!!

... prova a studiare QUI :wink:

Guglielmo

...dunque utilizzando il codice che segue ho fatto dei test cablando come segue:

  • TSOP34838: gnd, +v5, out ai pin 2(int 0) per il sensore front e pin 3(int 1) per il sensore posteriore;
  • diodo IR emettitore tramite R 100ohm al +v5 e gnd;
    Le barriere sono posizionate a 6 cm di distanza giusto per vedere se legge. Interrompendo il flusso n direzione ant-->post il monitor seriale visualizza dei lavori ma, ritengo pe ril cablaggio su millefori, le letture ogni tanto non avvengono.
    Ora passo al codice. L'ho trovato in rete e studiato. Non mi è del tutto chiaro però. L'architettura l'ho capita ni senso generale peroò non capisco quei led1 e led2 sui pin 12 e 13.
    Che ne pensate?
    Ovviamente il codice dovrà essere utilizzato con i componenti che devo ancora reperire laser e ricevitore laser e/o IR e fotodiodi PIN
/*
Fotodiodi o fototransistor sono nominati come attachInterrupt (0, front, CHANGE) collegato
con il pin digitale 2, e, attachInterrupt (1, posteriore, CHANGE) collegato al pin digitale 3
Coloro che vogliono provarlo possono collegare due pulsanti ai pin 2 e 3
I fotodiodi devono avere una resistenza tra 10k e 100kohm collegati al collettore (pin o gamba lunga) e questo al pin digitale
per assicurarsi che quando il raggio di luce viene interrotto, la tensione raggiunga 0 o massa
*/

// #include <LiquidCrystal.h>
 
#define MPS2FPSCOEFF 3.28084
#define LENGTH 0.159             
#define MICRO2SEKCOEFF 1000000

//LiquidCrystal lcd(4, 5, 6, 7, 8, 9);

volatile int stateFront = HIGH;
volatile int stateRear = HIGH;

int led1 = 12;                             
int led2 = 13;                             
int startChrono;
unsigned long startTime, stopTime, elapsed;
double fpsSpeed, mpsSpeed; 
 
void setup()
{
  Serial.begin(9600);
  //lcd.begin(16, 2);
  //lcd.setCursor(0, 0);
  //lcd.print("Super Chrono");
  Serial.print("Cronografo");
  //lcd.setCursor(0, 1);
  //lcd.print("by nv");
  delay(700);
  //lcd.clear();
  //lcd.setCursor(0, 0);
  //lcd.print("Initializing...");
  Serial.println("Inizializando");
  delay(700);
 // lcd.clear();
 
  startChrono = 0;
  elapsed = 0;
  fpsSpeed = mpsSpeed = 0;
 
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  /*
  Se tutto ok non cambiare nulla. Diversamente provare a cambiare CHANGE in RISING o LOW in 
  attachInterrupt(0, front, "      ") ed in attachInterrup(1, rear, "     ");
  */
  attachInterrupt(0, front, CHANGE); //0 (on digital pin 2) kanske falling/rising/low
  attachInterrupt(1, rear, CHANGE);  //1 (on digital pin 3)
//  attachInterrupt(0, front, RISING); //0 (on digital pin 2) kanske falling/rising/low
//  attachInterrupt(1, rear, RISING);  //1 (on digital pin 3)
  //lcd.setCursor(0, 0);
  //lcd.print("Take a shot!");
  Serial.println("Pronto per sparare?");
}
 
void loop()
{
  //Start counting when interrupted
  if(stateFront == LOW && startChrono == 0)
  {
    startTime = micros();  // Count microseconds since start
    startChrono = 1;       // Set Chrono flag
    digitalWrite(led1, HIGH);
  }
 
  // Stop counting and calculate speed
  if(stateRear == LOW && startChrono == 1)
  {
    stopTime = micros();  // Count microseconds since start
    startChrono = 0;      // Clear Chrono flag
    elapsed = stopTime - startTime;  // Calculate elapsed time (in micros)
 
    digitalWrite(led2, HIGH); // pin 13
    mpsSpeed = (LENGTH*(MICRO2SEKCOEFF)) / elapsed;            // s = v * t, v = s / t
   // fpsSpeed = mpsSpeed * MPS2FPSCOEFF;

    //lcd.clear();
    //lcd.print("Fps: ");
    //lcd.print(fpsSpeed);
    Serial.println("PPS(Piedi al secondo) ");
    Serial.print(fpsSpeed);
    //lcd.setCursor(0, 1);
    //lcd.print("m/s: ");
    //lcd.print(mpsSpeed);
    Serial.println("Metri al secondo ");
    Serial.print(mpsSpeed);
   
    startChrono = 0;
   
    delay(500);
    digitalWrite(led2, LOW);
    digitalWrite(led1, LOW);
   
  }
 
}

void front()
{
  stateFront = !stateFront;
}

void rear()
{
  stateRear = !stateRear;
}

Non sono un programmatore, ma non mi sembra cosi complessa ... in pratica cambia lo stato di due variabili nelle due ISR, e poi le usa per definire nel loop l'inizio e la fine del conteggio in microsecondi (o per essere precisi, di 4 in 4 microsecondi, dato che se non ricordo male, la massima risoluzione di micros e' 4) ... mi chiedo se non sarebbe piu semplice e veloce impostare invece direttamente tali valori nelle ISR, cioe' usare due variabili volatile unsigned long e fare variabile = micros direttamente nella ISR, evitando cosi tutto il "giro" di controlli nel loop (ma qui serve qualcuno che se ne intende, uno a caso, tipo ad esempio Guglielmo :smiley: che ci dica quale delle due e' la piu veloce) ... led1 e led2 mi sembra che li usa semplicemente per accendere i due led quando premi il pulsante per fare la lettura e li spegne subito dopo, probabilmente solo per risparmiare batteria ...il resto, da controllare, sono solo calcoli per convertire i microsecondi in tempo e velocita', conoscendo ovviamente la distanza fra i due fotodiodi ... ed in energia conoscendo il peso del pallino ...

Anche gli interrupt io personalmente userei rising o falling, quello che viene letto meglio, e non change, perche' tecnicamente e' scorretto usare change ... con change ogni pallino viene letto due volte da ciascun fotodiodo, quando interrompe il raggio e quando lo libera, e se il pallino e' sufficentemente lento questo introduce un'ulteriore errore, cambiando due volte lo stato della variabile ... in pratica rischi di invertirla due volte, riportandola allo stato iniziale e bloccando il tutto ...

Grazie dei preziosi consigli. In effetti anche a me non sembra complessa; dopo averla studiata l'ho compresa ma mi manca la capacità di realizzarla autonomamente. Sentiamo i consigli di qualche esperto di programmazione.
Un istruzione che non mi è chiara è la condizione LOW di questo rigo.

 if(stateFront == LOW && startChrono == 0)

O meglio l'ho compresa ma ho dubbi sul reale stato LOW.

Le prove fatte con i TSOP non sono soddisfacenti. Le letture non coerenti e si stranmisce e genera letture a caso.
Vorrei provare con due fotodiodi a due piedini visto che il TSOP ne ha tre...come collego il fotodiodo?

Etemenanki:
... uno a caso, tipo ad esempio Guglielmo ...

Io collegherei i due fotodiodi a due pin INT facendo si, come hai detto, che scatti solo su uno dei due fronti (se normalmente il segnale è HIGH e va LOW al passaggio del pallino, lo farei sul fronte di discesa, in caso contrario sul fronte di salita).

In entrambe la ISR farei solo l'assegnazione di una variabile volatile (intendo una diversa variabile per ogni ISR) al valore di micros() al momento dello scatto dell'interrupt.

Nel loop() se trovo entrambe le variabili diverse da zero, faccio la differenza per calcolare il tempo e le azzero di nuovo in attesa della nuova misura.

La parte software è molto semplice, quella più delicata è quella hardware ... ::slight_smile:

Guglielmo

P.S.: Convermo che su un AVR a 16MHz la risoluzione di micros() è 4 μsec.

Guglielmo: quindi mi confermi anche tu che, come da mia impressione, sarebbe meglio fare direttamente le assegnazioni nelle ISR, invece che come in quel programma ? ... a me dava l'idea di una complicazione inutile fatta cosi, ma non ero sicuro se fosse stato fatto perche' assegnare il valore di micros ad una unsigned long richiedesse piu tempo che invertire uno stato di una byte, o per chissa' quale altra ragione ...

Pensavo, come hai detto anche tu, che si puo far fare al loop solo il confronto finale ... magari come "finezza" e per risparmiare batterie, ci si potrebbe aggiungere un pulsante che azzera le due variabili ed accende i led, come "start" per la lettura ... tipo, nel setup le definisci entrambe a valore 1 (valore che sara' molto improbabile abbiano mai in seguito), per cui il micro puo stampare il messaggio iniziale, o la richiesta di premere start, eccetera, quando le trova cosi ... quando premi start, le azzeri, accendi i due led, aspetti un mezzo secondo, dai la conferma dello start (magari si aggiunge anche un buzzer piezo per i vari bip) ed inizia un conteggio di, mettiamo, 30 o 60 secondi ... se nulla succede entro quel tempo, resetti tutto al valore iniziale e spegni i led (cosi risparmia anche batteria), se invece passa il pallino, quando non valgono piu zero entrambe il loop puo spegnere i led, fare i calcoli e visualizzarli, e mettersi in attesa di un'altra pressione del pulsante per la successiva lettura ... ci sta ?

vince59:
...
Le prove fatte con i TSOP non sono soddisfacenti...

Non lo saranno mai ... i TSOP non sono fotodiodi, ma ricevitori integrati con anche altra elettronica dentro ... sono tipo 10000 volte piu "lenti" di un vero fotodiodo, se usati in quel modo ...

Etemenanki:
... ci sta ?

... se si ha necessità di alimentare il tutto a batterie e di risparmiare corrente, sicuramente si può fare una cosa come quella che dici :slight_smile:

Guglielmo