Go Down

Topic: CRONOGRAFO BALISTICO (Read 11114 times) previous topic - next topic

vince59

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



Etemenanki

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 ...
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

gpb01

Guglielmo, aiutami sennò spacco il PC co na capocciata!!!!
... prova a studiare QUI ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

vince59

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

Code: [Select]

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

Etemenanki

#34
Oct 13, 2018, 09:30 am Last Edit: Oct 13, 2018, 09:34 am by Etemenanki
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 :D 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 ...
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

vince59

#35
Oct 13, 2018, 01:58 pm Last Edit: Oct 13, 2018, 03:06 pm by vince59
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.

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

gpb01

#36
Oct 13, 2018, 04:36 pm Last Edit: Oct 13, 2018, 04:38 pm by gpb01
... 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 ... ::)

Guglielmo

P.S.: Convermo che su un AVR a 16MHz la risoluzione di micros() è 4 μsec.
Search is Your friend ... or I am Your enemy !

Etemenanki

> 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 ?
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Etemenanki

...
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 ...
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

gpb01

#39
Oct 13, 2018, 05:36 pm Last Edit: Oct 13, 2018, 05:36 pm by gpb01
... 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 :)

Guglielmo
Search is Your friend ... or I am Your enemy !

Etemenanki

Ho immaginato di si, perche' in fondo parla di un'oggetto da collegare alla volata della carabina, probabilmente in poligono o su un campo di tiro sportivo, dove non e' che ti mettano a disposizione tante prese di corrente ;)
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

vince59

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



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

Guglielmo

P.S.: Convermo che su un AVR a 16MHz la risoluzione di micros() è 4 μsec.
Comincerei a stabilire qualche punto fermo:
HARDWARE:
utilizzare due led IR e due fotodiodi PIN (int 0 ed int 1). A livello elettrico i led IR alimentati continuamente magari con una resistenza verso il positivo per limitare l'assorbimento..diciamo 100ohm.
Per i fotodiodi posso provare il collegamento a polarizzazione inversa suggerito da etemenanki ((catodi dei diodi al +5V, anodi ai pin di arduino, resistenze fra i pin e massa come pull-down e per polarizzare inversamente il diodo). Io credo che il segnale sia sufficente altrimenti amplifico con un BC337 o simile.
Ricordate che sono cmq in attesa di ricevere i laser tx e rx. Provo a buttare giù uno schema elettrico

SOFTWARE:
qui vi chiedo di farmi comprendere le vostre osservazioni perchè non mi sono del tutto chiare laddove Guglielmo recita:

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.

gpb01

#42
Oct 13, 2018, 09:08 pm Last Edit: Oct 13, 2018, 09:08 pm by gpb01
SOFTWARE:
qui vi chiedo di farmi comprendere le vostre osservazioni perchè non mi sono del tutto chiare ...
... cosa non ti è chiaro ? ? ?

Guglielmo
Search is Your friend ... or I am Your enemy !

vince59

#43
Oct 13, 2018, 10:09 pm Last Edit: Oct 13, 2018, 10:38 pm by vince59
il discorso dell'ISR:

in entrambe la ISR farei solo l'assegnazione di una variabile volatile (intendo una diversa variabile per ogni ISR)
qual'è l'ISR :-(
e il concetto successivo:
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.

PS: sto provando il codice con due tastini o facendo variare lo stato degli interrupt ma funziona strano...il primo valore è un valore coerente poi salta ad un numero a 8 cifre come se si stranisse

gpb01

#44
Oct 14, 2018, 09:30 am Last Edit: Oct 14, 2018, 09:34 am by gpb01
Molto grossolanamente, giusto per dare un'idea:

Code: [Select]

volatile unsigned long t1, t2;
unsigned long deltaT;
...
...
void ISR1(void) {
   t1 = micros();
}

void ISR2(void) {
   t2 = micros();
}
...
...
void setup () {
...
...
t1 = 0;
t2 = 0;
...
...
}

void loop() {
   ...
   ...
   if ((t1 != 0) && (t2 != 0)) {
      deltaT = t2 - t1;
      t1 = 0;
      t2 = 0;
   }
   ...
   ...
}

Nel caso di uso di pulsanti, per provare, DEVI necessariamente prevdere un debounce hardware (rete R/C in ingresso) o non funzionerà mai.

Guglielmo
Search is Your friend ... or I am Your enemy !

Go Up