Progetto per telecine partendo da proiettore: passo passo e macchina fotografica

Buongiorno ragazzi,
spero di trovarvi bene. Mi chiamo Nicola, sono un fotografo, e sto cercando di realizzare con Arduino un controller per un Telecinema.

Vi spiego: ho delle pellicole 8mm (immaginatevi le pellicole del cinema, con migliaia di fotogrammi da proiettare) che voglio scansionare frame by frame. Voglio modificare un proiettore sostituendo il motore con un motore passo passo e relativa cinghia/riduttore:

Arduino ha un controller (joystic) per controllare il motore passo passo. Se sposto la leva a sinistra il motorino gira antiorario (riavvolge), se sposto la leva a destra il motorino gira orario (avvolge), se invece clicco parte la procedura di scansione. Procedura che posso riassumere come:
a. Motore gira per un determinato numero di giri, poi si ferma, mettendo in posizione il fotogramma successivo;
b. Arduino dice alla reflex di scattare una foto;
c. --> torna ad a.

Finora sono riuscito a cablare il joystic ed il motore passo passo, e il fast forward e fast rewind funzionano (quindi se sposto la leva indietro il motore riavvolge e se sposto la leva avanti il motore avvolge).

Questo è il codice che uso:

/*
 * TeleCine V0.2 - Joystick funzionante
 */
 
// Includo libreria Stepper
#include <Stepper.h>
 
// Definisco numero di passi per ogni giro
#define STEPS 32
 
// Definisco i pin dello stepper
#define IN1  11
#define IN2  10
#define IN3   9
#define IN4   8
 
// Inizializzo la libreria Stepper
Stepper stepper(STEPS, IN4, IN2, IN3, IN1);
 
// Joystic output connesso ad A0
#define joystick  A0
 
void setup()
{
  
}
 
void loop()
{
  // leggo il valore analogico dal potenziometro
  int val = analogRead(joystick);
 
  // se il joystick è a metà ferma il motore
  if(  (val > 500) && (val < 523) )
  {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
  }
 
  else
  {
    // muove il motore nella prima direzione
    while (val >= 523)
    {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 523, 1023, 5, 500);
      // Setto la velocità del motore
      stepper.setSpeed(speed_);
 
      // Muovo il motore (1 step)
      stepper.step(1);
 
      val = analogRead(joystick);
    }
 
    // Muovo il motore nell'altra direzione
    while (val <= 500)
    {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 500, 0, 5, 500);
      // set motor speed
      stepper.setSpeed(speed_);
 
      // Muovo il motore (1 step)
      stepper.step(-1);
 
      val = analogRead(joystick);
    }
 
  }
 
}

Uso Arduino Uno R3, preso da un kit che ho comprato su Amazon con una guida di base e diversi componenti, si chiama Elegoo Most Complete Starter Kit UNO R3 Project.

Adesso devo implementare la procedura che ho descritto prima.
Quindi:
Se clicco sul joystick (che a quanto ho capito ha il click come comando digitale, non analogico) parte la seguente routine:

  1. a. Il motore passo passo fa un giro in senso orario e si ferma (semplifichiamo ad un giro per adesso);
  2. b. Arduino dice alla reflex di scattare (va collegata con connettore minijack)
  3. c. torna ad a.

Se clicco di nuovo sul joystick la procedura si ferma.

Mi date per favore una mano ad implementare questa routine? Non riesco ad uscirne!

Grazie mille,
Nicola.

Ciao.
Prova quanto segue per vedere come va

/*
   TeleCine V0.2 - Joystick funzionante
*/

// Includo libreria Stepper
#include <Stepper.h>

// Definisco numero di passi per ogni giro
#define STEPS 32

// Definisco i pin dello stepper
#define IN1  11
#define IN2  10
#define IN3   9
#define IN4   8

// Inizializzo la libreria Stepper
Stepper stepper(STEPS, IN4, IN2, IN3, IN1);

// Joystic output connesso ad A0
#define joystick  A0

#define joystick_button ?? // Collega il pulsante al pin ?? e a gng 
#define camera ?? // Collega il + del Jack al pin ?? l'altro polo a gnd (presumo che la camera si attivi con un + impulso) 
#define passi ???// passi necessari per avanzare di un fotogramma 
#define tempo ???// tempo necessario per l'esposizione di un fotogramma 

void setup() {
  pinMode (joystick_button, INPUT_PULLUP);
  pinMode (camera, OUTPUT);
}

void loop() {
  // leggo il valore analogico dal potenziometro
  int val = analogRead(joystick);
  // se il joystick è a metà ferma il motore
  if (  (val > 500) && (val < 523) ) {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
    if (digitalRead (joystick_button) == LOW) {//leggiamo il pulsante del joystick
      reflex (); // se premuto richiama la funzione di copia
    }
  }

  else {
    // muove il motore nella prima direzione
    while (val >= 523) {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 523, 1023, 5, 500);
      // Setto la velocità del motore
      stepper.setSpeed(speed_);
      // Muovo il motore (1 step)
      stepper.step(1);
      val = analogRead(joystick);
    }

    // Muovo il motore nell'altra direzione
    while (val <= 500) {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 500, 0, 5, 500);
      // set motor speed
      stepper.setSpeed(speed_);
      // Muovo il motore (1 step)
      stepper.step(-1);
      val = analogRead(joystick);
    }
  }
}

void reflex () {
  delay (100);// anti rimbalzo
  while (digitalRead (joystick_button) == LOW); //assicurati che il pulsante sia rilasciato
  delay (100);// anti rimbalzo
  stepper.setSpeed(500); // o la velocità più appropriata
  while (digitalRead (joystick_button) == HIGH) { //tutto viene eseguito ripetutamente fino a una nuova sequenza di tasti
    stepper.step(passi);// avanza di un fotogramma
    digitalWrite (reflex, HIGH); // Impulso di attivazione per la camera
    delay (????); //tempo necessario per la reazione della camera
    digitalWrite (reflex, LOW);// fine dell'impulso di attivazione
    delay (tempo);//tempo necessario per l'esposizione di un fotogramma
  }
  delay (100);// anti rimbalzo
  while (digitalRead (joystick_button) == LOW); //assicurati che il pulsante sia rilasciato
  delay (100);// anti rimbalzo
}

Saluti.

1 Like

Ciao, grazie dell'aiuto! Purtroppo sono ancora al passo precedente, devo collegare la camera ad Arduino. Secondo te questo circuito può andare?
http://www.glacialwanderer.com/hobbyrobotics/?p=13

Se si provo a fare il circuito (dovrei aver già tutti i componenti) e ad usare il codice nel link; se vedo che tutto funziona provo ad adattare (anche se sicuramente avrò bisogno di qualche aiutino) il codice che mi hai dato tu!

Se hai dei consigli da darmi ovviamente sono super graditi!

Sì, funzionerà, ma così com'è si richiede troppa corrente dai pin di arduino e possibilmente dalla fotocamera, riuscendo a danneggiarli. Metterei alcuni resistori di limitazione della corrente per sicurezza.
Transistores
Saluti

1 Like

Ciao!
Dunque, son finalmente riuscito a mettermi sotto al circuito, ci sono alcune cose che non vanno.

Qui il codice usato (il tuo con assegnati i PIN etc):

/*
   TeleCine V0.3 - Joystick funzionante
*/

// Includo libreria Stepper
#include <Stepper.h>

// Definisco numero di passi per ogni giro
#define STEPS 32

// Definisco i pin dello stepper
#define IN1  11
#define IN2  10
#define IN3   9
#define IN4   8

// Inizializzo la libreria Stepper
Stepper stepper(STEPS, IN4, IN2, IN3, IN1);

// Joystic output connesso ad A0
#define joystick  A0

#define joystick_button 4 // Collega il pulsante al pin ?? e a gng 
#define camera 6 // Collega il + del Jack al pin ?? l'altro polo a gnd (presumo che la camera si attivi con un + impulso) 
#define passi 16// passi necessari per avanzare di un fotogramma 
#define tempo 1000// tempo necessario per l'esposizione di un fotogramma 

void setup() {
  pinMode (joystick_button, INPUT_PULLUP);
  pinMode (camera, OUTPUT);
}

void loop() {
  // leggo il valore analogico dal potenziometro
  int val = analogRead(joystick);
  // se il joystick è a metà ferma il motore
  if (  (val > 500) && (val < 523) ) {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
    if (digitalRead (joystick_button) == LOW) {//leggiamo il pulsante del joystick
      reflex (); // se premuto richiama la funzione di copia
    }
  }

  else {
    // muove il motore nella prima direzione
    while (val >= 523) {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 523, 1023, 5, 500);
      // Setto la velocità del motore
      stepper.setSpeed(speed_);
      // Muovo il motore (1 step)
      stepper.step(1);
      val = analogRead(joystick);
    }

    // Muovo il motore nell'altra direzione
    while (val <= 500) {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 500, 0, 5, 500);
      // set motor speed
      stepper.setSpeed(speed_);
      // Muovo il motore (1 step)
      stepper.step(-1);
      val = analogRead(joystick);
    }
  }
}

void reflex () {
  delay (100);// anti rimbalzo
  while (digitalRead (joystick_button) == LOW); //assicurati che il pulsante sia rilasciato
  delay (100);// anti rimbalzo
  stepper.setSpeed(500); // o la velocità più appropriata
  while (digitalRead (joystick_button) == HIGH) { //tutto viene eseguito ripetutamente fino a una nuova sequenza di tasti
    stepper.step(passi);// avanza di un fotogramma
    digitalWrite (reflex, HIGH); // Impulso di attivazione per la camera
    delay (1000); //tempo necessario per la reazione della camera
    digitalWrite (reflex, LOW);// fine dell'impulso di attivazione
    delay (500);//tempo necessario per l'esposizione di un fotogramma
  }
  delay (100);// anti rimbalzo
  while (digitalRead (joystick_button) == LOW); //assicurati che il pulsante sia rilasciato
  delay (100);// anti rimbalzo
}

  1. Quando "clicco" il joystick la procedura parte: il motore fa un movimento, poi si ferma (presumo per mandare il segnale di scatto) poi riparte etc.
  2. Se RIpremo il joystick però la procedura non si ferma, continua in loop e l'unico modo di interromperla è togliere l'alimentazione.
  3. Alla macchina putroppo non arriva nessun segnale, niente di niente, come se non sentisse nessun impulso dal jack. A tal proposito, ho smontato il telecomando che ho "sacrificato" per prendere il jack già cablato: ad occhio la messa a fuoco avviene unendo filo nero e filo verde, lo scatto invece unendo filo nero, verde e rosso.

Ho seguito lo schema postato poco sopra, unica differenza è che le resistenze a mia disposizione eran da 330, quindi R1 e R2 sono da 330 mentre R3 e 4 sono due da 330 in serie.

Se può far comodo posso allegare foto sia della breadboard con il circuito provvisorio sia del telecomando!

Grazie mille per ogni aiuto possa ricevere!

Solo un suggerimento, per quel tipo di lavori, bisognerebbe usare una macchina senza l'autofocus, oppure disabilitarlo (mettendo ovviamente a fuoco il tutto manualmente), perche' ogni volta che si fa la procedura dello scatto con l'autofocus attivo, la maggior parte delle macchine completa il controllo del fuoco prima dello scatto a prescindere dalla pressione del secondo click del pulsante (per cui anche se arriva l'impulso, se dura abbastanza c'e' il ritardo della messa a fuoco prima dello scatto, se non dura abbastanza la camera lo ignora) ... questo non capita con tutte le camere, ma buona parte si, e non sono molte quelle che possono alterare il ciclo nel loro menu (a proposito, che macchina stai usando ? )

Inoltre ci sono diversi modelli che richiedono che la sequenza di chiusura dello switch venga rispettata, o lo considerano un'errore ... quindi se si chiudono entrambi i fili insieme, o non si chiude il fuoco prima dello scatto, alcune macchine non scattano (la sequenza corretta sarebbe chiudere prima il contatto del fuoco, e dopo, mentre e' chiuso, chiudere anche quello dello scatto)

1 Like

Il modo in cui hai impostato i tempi, dovete premere il joystick per almeno un secondo e mezzo o più. Prova con quel tempo per vedere se il codice si interrompe.
La camera non scattava perché avevamo collegato solo un cavo con il gnd e ora dite che entrambi i cavi devono essere collegati, è facile da risolvere ma prima di farlo devi definire come funziona la tua camera come suggerisce molto bene @Etemenanki
Saluti.

1 Like

Ciao Etemenanki, eccomi qui. Quello che scrivi ovviamente ha senso: mai pensato di usare la macchina in autofocus per questo lavoro, ovviamente lavorerò in fuoco manuale con soffietto in quanto si tratta di scatti macro di un dettaglio di 8x12mm. Il corpo macchina è una Canon Eos R, per prova con un 100L macro.

Dopo aver osservato meglio il telecomando, e fatto alcune prove, il problema è che il circuito che avevo trovato non si adatta a questo modello.

Qui dettaglio del telecomando (non ha batterie, quindi l'alimentazione viene solo dalla macchina):

Quando nero e verde si chiudono parte la messa a fuoco; quando nero verde E rosso si chiudono parte lo scatto. Solo verde e rosso non danno nessun risultato ovviamente. Dato che lavorerà in fuoco manuale, si può anche cortocircuitare permanentemente nero e verde (la macchina in fuoco manuale non sente l'impulso) e comandare con Arduino solo la chiusura del rosso (quindi immagino basti un solo transistor).

Il cavo del telecomando ha anche un filo bianco, ma non è collegato.

Mi date una mano per circuito e codice? Una volta che la procedura funzionerà (giro del motore-scatto-giro del motore etc) spero di potermela cavare da solo :smiley:

Grazie ancora, siete molto preziosi, Nicola.

Personalmente ti consiglierei di usare un'opto, oppure anche meglio un piccolo rele' REED (cosi la macchina rimane elettricamente isolata da Arduino, e con il rele' "vede" un contatto pulito come quello del telecomando)

Poi per il trascinamento della pellicola potresti usare una forcellina ottica, o meglio ancora una rotella dentata, magari recuperata da un vecchio proiettore, che "ingrani" nei fori della pellicola, per essere sicuro al 100% del posizionamento del fotogramma (se si usa una forcella ottica, bisognerebbe cercare di modificarla togliendo il led IR e mettendone uno giallo o verde, questo perche' nelle pellicole sviluppate, di solito quello che all'occhio appare nero e' praticamente trasparente agli infrarossi) ... oppure usare una bella demoltiplica per il passo-passo, sara' piu lenta ma permettera' di avere maggiore precisione (anche se di solito niente batte la precisione di un sensore ottico)

Non paro di precisione in senso generico, ma di "accumulo dell'errore" ... anche solo un centesimo di mm di scarto, dopo un centinaio di fotogrammi fa gia un mm di errore.

Il sistema migliore sarebbe l'avere un vecchio proiettore da "cannibalizzare" per recuperarci il meccanismo di trascinamento del fotogramma (la parte che sposta fisicamente la pellicola di un fotogramma alla volta quando il diaframma e' chiuso, piu preciso di quello non credo si possa fare, e non servirebbe neppure un'encoder o una forcella ottica sulla pellicola, solo un contatto sulla meccanica, pero' serve un proiettore rottamato, e non e' che se ne trovino cosi tanti in giro)

Io posso darti una mano per l'hardware, con il codice ci litigo un po, ma ancora non arrivo a capire un decimo di quello che gia sa la maggior parte degli utenti qui.

Per questo motivo sono d'accordo con @Etemenanki nel non utilizzare transistor e nell'utilizzo di un relè per unire i fili necessari. Potrebbe essere qualcosa del genere:
https://www.amazon.it/AZDelivery-Modulo-livello-KY-019-Arduino/dp/B07TYG14N6/ref=sr_1_14
Il codice che ho proposto prima, cambialo nel seguente. Il pulsante del joystick deve necessariamente andare al pin 2 poiché utilizzo le interruzioni e il pin che comanda il relè l'ho messo in 13, giusto per provarlo con i led della scheda arduino. Puoi collegarlo a qualsiasi altro pin libero.

/*
   TeleCine V0.3 - Joystick funzionante
*/

// Includo libreria Stepper
#include <Stepper.h>

// Definisco numero di passi per ogni giro
#define STEPS 32

// Definisco i pin dello stepper
#define IN1  11
#define IN2  10
#define IN3   9
#define IN4   8

// Inizializzo la libreria Stepper
Stepper stepper(STEPS, IN4, IN2, IN3, IN1);

// Joystic output connesso ad A0
#define joystick  A0

#define joystick_button 2 // Collega il pulsante al pin 2 e a gng (obbligatorio il pin 2) 
#define camera 13 // collegare il pin all'ingresso del modulo relè (Lo stato si rifletterà nel led della targa) 
#define passi 16// passi necessari per avanzare di un fotogramma 
#define tempo 1000// tempo necessario per l'esposizione di un fotogramma 
volatile bool fermare;

void setup() {
  pinMode (joystick_button, INPUT_PULLUP);
  pinMode (camera, OUTPUT);
}

void loop() {
  // leggo il valore analogico dal potenziometro
  int val = analogRead(joystick);
  // se il joystick è a metà ferma il motore
  if (  (val > 500) && (val < 523) ) {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
    if (digitalRead (joystick_button) == LOW) {//leggiamo il pulsante del joystick
      reflex (); // se premuto richiama la funzione di copia
    }
  }

  else {
    // muove il motore nella prima direzione
    while (val >= 523) {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 523, 1023, 5, 500);
      // Setto la velocità del motore
      stepper.setSpeed(speed_);
      // Muovo il motore (1 step)
      stepper.step(1);
      val = analogRead(joystick);
    }

    // Muovo il motore nell'altra direzione
    while (val <= 500) {
      // Mappa la velocità tra 5 e 500 rpm
      int speed_ = map(val, 500, 0, 5, 500);
      // set motor speed
      stepper.setSpeed(speed_);
      // Muovo il motore (1 step)
      stepper.step(-1);
      val = analogRead(joystick);
    }
  }
}

void reflex () {
  delay (100);// anti rimbalzo
  while (digitalRead (joystick_button) == LOW); //assicurati che il pulsante sia rilasciato
  delay (100);// anti rimbalzo
  stepper.setSpeed(500); // o la velocità più appropriata
  fermare = false;
  attachInterrupt(digitalPinToInterrupt(joystick_button), Pulsante_servizio, LOW);// gli interrupt sono attivati 
  while (fermare == false) { //La sequenza viene ripetuta finché non viene premuto il joystick
    stepper.step(passi);// avanza di un fotogramma
    delay (250);
    digitalWrite (camera, HIGH); // Impulso di attivazione per la camera
    delay (tempo);//tempo necessario per l'esposizione di un fotogramma
    digitalWrite (camera, LOW);// fine dell'impulso di attivazione
  }
  detachInterrupt(digitalPinToInterrupt(joystick_button));// gli interrupt sono disabilitati 
  while (digitalRead (joystick_button) == LOW); //assicurati che il pulsante sia rilasciato
  delay (100);// anti rimbalzo
}

void Pulsante_servizio () {
  fermare = true;
}

L'ho provato e funziona.
Saluti.

pensavo piu ad una cosa del genere (o simile)

piu piccoli, piu silenziosi, durano di piu, consumano molto meno :wink:

Sì, anch'io userei qualcosa del genere, ma devi montarli su un PCB, saldare ecc, non so se @ncdotcom può farlo.
saluti

Ciao Etemenanki, ti ringrazio per gli appunti. Purtroppo a quanto pare siamo "complementari": per me la meccanica non è un problema ma arduino e programmazione si :smiley:

Il proiettore l'ho già cannibalizzato ed è quasi pronto. Ho tolto tutto ciò che era relativo al vecchio motore, già fatto una staffa per un NEMA 17 e preso la puleggia, rimosso con il dremel le palette dell'otturatore e modificato ed allargato la finestra di proiezione, così da usare la struttura del proiettore come trascinatore e porta bobine. Ho già previsto un sensore ottico od un interruttore a leva azionato dall'otturatore modificato senza palette, in modo che se non raggiungo la precisione voluta con il passo passo (e come dici tu non riesco a contrastare via software l'accumulo di errore) posso aggiungere uno "stop" fisico senza problemi. Nel caso abbia bisogno di supporti ad hoc posso sempre progettarli e stamparli in ABS qui a casa. Ma ti ringrazio assolutamente, due teste son sicuramente meglio di una!

Citazione gonpezzi
Sì, anch'io userei qualcosa del genere, ma devi montarli su un PCB, saldare ecc, non so se @ncdotcom può farlo.
saluti

No problem per PCB, saldature etc, quindi una volta ultimato il progetto mi farò dei PCB ad hoc, ma per le prove preferivo usare una breadboard con cablaggio dupont per praticità: oltre a questo, mi piace "capire" cosa sto facendo, per questo andavo avanti con il progetto passo dopo passo. A questo punto che faccio, prendo quello linkato da Etemenaki (c'è qualcosa di simile su Amazon, mi è più comodo e più veloce rispetto ad ebay? Il costo non è un problema) o quello linkato da gonpezzi?

Considerate che come pezzi e sensori ho a disposizione tutti quelli di questo kit:

Quindi se posso utilizzare pezzi di questo kit sarebbe più semplice!

A questo punto attendo voi su come procedere o se acquistare altro materiale. Vi devo una birra!

Su amazon in prime solo 10 pezzi per 18 Euro (SIP anziche' DIL, cambia la forma ma non la sostanza), oppure 5 per 8 Euro ma spediti sempre dalla Cina ... si fa prima ad andare in un negozio di componenti elettronici e chiedere al banco, oppure usare Mouser, Digikey, Farnell, RS, ma solo se si ha tanta roba da acquistare altrimenti ti massacrano con le spese di spedizione ...

In quel kit hai un relè 5v, ti sarà facile controllarlo con un pin arduino, inoltre hai già fatto il montaggio.
Nel circuito che hai fatto nel post #4, usando un transistor con le due resistenze serie 330 che hai collegato alla base basta scambiare la resistenza del collettore, (la r1 o r2), per il relè e praticamente hai il modulo relè venduto su ali o amazon.

Perfetto! E poi uso il codice come da tuo post #10? Se la risposta è affermativa, domani pomeriggio provo il tutto e vi tengo aggiornati!

La risposta è affermativa

Dunque, montato tutto, sento il relè che fa clic ma la macchina non scatta. Giusto per esser sicuri di aver montato il relé nel modo giusto:

b1f586a8e034033ac99cc01727dd2b9857cece3f_2_690x393 copia
Relay-Pinout

1 va su Coil 1
2 va su Coil 2
3 va su NO
4 va su NC

e su Com?

Scusate la domanda banale!

Secondo quanto ho capito dal funzionamento del telecomando, il cavo rosso va collegato a 5 del relè.
E il codice reagisce già al pulsante e si ferma?

Cosa intendi con questo? Non ho capito.