domingo, 29 de junio de 2014

Aprovechando la primavera (II)

Tal y como dije, la  primavera es mi estación preferida para fotografiar pues los contrastes de colores suelen ser más accentuados y los verdes son verdes, sólo hay que esperar un dia nítido para ganar en profundidad de campo. Asi que aqui vienen otro grupo de Gigapanes realizadas durante la primavera con el robot panorámico XS.

Barcelona desde el turó de la Rovira:

La primera que hice (siempre por orden cronológico), fué de Barcelona ciudad desde el turó de la Rovira (bunkers anti aereos) , es un lugar que a todos los que visiten esta ciudad les recomiendo que pierdan unas horas para gozar de las vistas de este sitio. Llevaba muchos meses esperando el momento, habia subido a varios lugares intentando buscar el sitio perfecto y este casi lo era. El casi es porque es un lugar muy transitado por visitantes, curiosos, vamos que no te da sni cuenta y tienes mas de un centenar de personas a tu lado y como es de comprender para mi y mi invento es una situación molesta. 

Resumen, era un domingo despejado porque por la noche del sábado hizo viento lo que propiciaba que no hubiera la típica contaminación que caracteriza esta ciudad. Fué cuestión de comer temprano para poder llegar a este emblematico lugar con la esperanza de no encontrarme mucha gente y asi fué.

Todos los astros se alinearon y aqui hay la captura resultante tras unir las 693 fotos (33 columnas x 21 filas) y una resolución próxima a los 12 GPx.:


Me habria gustado realizarla con mi robot grande con el sigma 150-500 pero no me atreví por culpa de los curiosos, con el 18-200 de Nikkor tardé menos de una hora, mientras que con el Sigma habrian sido 4 horas, un espacio de tiempo muy grande.

En grande la podéis ver en http://gigapan.com/gigapans/155386

Barcelona desde Puig Castellar:

Acto seguido y para aprovechar la tarde del domingo me desplazé hasta otro sitio con buenas vistas hacia Barcelona y comarca, justo en el poblado ibérico de Puig Castellar situado en el término municipal de Badalona.

En la cima de esta montaña hacia mucho viento por lo que el proyecto no pintaba muy bien, a ratos me veia obligado a pausar el proyecto al tener grandes ráfagas de viento que parecia que tenia que salir el trípode + robot volando hasta Mallorca! 

Fué la primera vez que utilizaba el estabilizador a la hora de tomar capturas y eso significó que a poco más de la mitad del proyecto me quedé sin batería y tuve que desamblar la camara respecto al robot para poder cambiar la batería con el riesgo que comporta.

Aunque parezca mentira aqui todo y estar perdido en la montaña, el número de curiosos se multiplicó con las frases típicas de "ponlo en el youtube, en que canal de tv va a salir...", en fín que tengo un imán para atraer a los curisosos y a los locos!

Todo y eso, al final no hubo ningún problema a la hora de unir las fotografias y componer la gigafoto de 6 GPx. que podeis verla en grande en http://gigapan.com/gigapans/155459



El plà de Bages:

La siguiente fué realizada sobre Santpedor , en Castellnou de Bages con una vista al sur de la comarca del Bages. En esta ocacisón quedé con Jordi para mostrarle como funcionaba mi robot y como realizaba este tipo de fotografia en cuestión de conceptos de fotografia.

En este caso fueron 532 fotografias (28 lineas x 29 columnas) con la Nikon d5200 y el Nikkor 18-200.


La resolución final de 8.8 GPx, y también podeis navegar por ella en http://gigapan.com/gigapans/155500

Sant Joan de Vilatorrada:

A pocos minutos en coche de mi vivienda fué tomada la siguiente gigafoto, en este caso fotografié el pueblo de Sant Joan de Vilatorrada con 816 capturas (14.5 GPx) , y el resultado fué el siguiente:


Sallent:

En esta ocasión la cosa salió rana...y tuve que repetirla. El problema fué debido a una gran tontería...

Fuí un domingo por la mañana, y empecé a realizar capturas, hasta llegar al campo de futbol en el que estaban haciendo la media parte del partido de futbol y pausé el robot. Pasaban los minutos y los niños no seguian el partido por lo que decidí seguir con mi proyecto, y tras fotografiar el campo, reemprenden el partido. En ese momento intenté repetir esas tomas pero se me descuadró el solape entre capturas y luego el software AutoPano Giga no era capaz de unirmelas correctamente provocandome unos duplicados de casi una fila, por lo que decidí volver una semana después con la Loli para que viera como realizo este tipo de fotografias.

En esta ocasión estrené el sistema de alimentación ininterrumpido hacia la camara (explicado en otro post) y un Tamron 70-300 mm y todo fué bién, sin ninguna anormalidad digna de destacar.

Si la quereis ver en grande (23.3 GPx), sólo hay que visitar el siguiente link:


Martorell:

Otro de los lugares pendientes...pasando por la autopista siempre veia la industria química y pensaba en los infinitos detalles que albergaría una fotografia por lo que un sábado soleado por la tarde decidí ir a fotografiar el paisaje.

Fueron algo más de 1100 fotografias para componerla, pero dió mucha guerra debido a dos motivos principalmente: 

* Los coches cortados y matriculas que habria que borrar
* Los cables de alta tensión que no quedaron bién solapados por culpa del punto nodal desajustado.

Mediante Photoshop suelo reparar anormalidades pero se hizo muy pesado al trabajar con un archivo PSD de 150 GBytes todo y utilizar un iMac core i7 con 32 GB de RAM

El resultado de 26.8 GPx (aunque no satisfactorio para mi todo y la guerra que me dió) es el siguiente:


Nota> Se observan varias tomas con una intensidad diferente, pero no sé a que fue debido pues el revelado siempre lo hago en lote con los mismos ajustes en todas las fotos...
Por cierto, después de realizar esta fotografia tuve que hacer limpieza del sensor utilizando alcohol isopropilico para sacar unas motas de polvo que tenia en el CMOS.
Durante la limpieza observé que en un lateral del receptáculo dónde se mueve el espejo de la cámara tenia un desgaste como si el propio espejo lo hubiera rascado y quizas la tela negra era las motas de suciedad que residian en el sensor...en fín que la cosa no pintaba bién.

Balsareny:

Finalmente esta es la última de este post. Cabe decir que horas antes estube haciendo otra gigafoto , que no pude "revelar" porque durante las capturas se perdieron magicamente unas 20 fotos. Lo único que observé es que el ruido del espejo era anormal, como si no actuara correctamente cosa que me dejó preocupado. La desaparición de dichas fotos no me percaté hasta que fuí a procesar la foto.

Pero vamos a la que vamos...

Llegé al sitio, tenia que subir los trastos una cuesta de unos 50 metros, con un sol que deslumbrava, pues tras hacer esas carreras arriba abajo arriba con los trastos tardé 10 minutos en recuperarme. No tenia ni una sombra por lo que me refugié en la que producia un triste arbusto.

Monté todo el invento y empecé con las capturas. Volví a escuchar los ruidos anormales en el espejo, pausé el robot, y apagé la camara y la volví a encender y a partir de ese momento no falló mas...

Una vez en casa me percaté que me habian desaparecido 5 fotos, las cuales eran "fáciles" de disimular pues eran de arbustos por lo que manos a la obra y tras unas horas de photoshop parece que ha quedado  disimulado.

Tras procesar las 1372 imagenes, este es el resultado final de 27 GPx. que deseo que os guste:


Deseo que en general os hayan gustado.
Saludos y DIY !

domingo, 18 de mayo de 2014

Aprovechando la primavera

Llega la primavera, mi epoca preferida a nivel de fotografia, los campos verdes , los cielos azules, una buena temperatura y muchas dias con una buena visibilidad, ya no existe la niebla del invierno ni esa "calicha" que se ocasiona en verano. Aparte es una epoca en que de vez en cuando cae un chaparrón y sirve para limpiarlo todo, inclusive el ambiente. 

En fín que ha sido una temporada para realizar Gigapanes o Gigafotos, en este post os intentaré hacer un resumen de mis experiencias:

Empiezo por una Gigafoto realizada en mi pueblo natal, Súria , en la cual se puede ver el rio Cardener. Este dia fué un poco desastre con el tema baterias, el problema empezó cuando un domingo por la mañana y viendo la climatologia exterior uno decide ir a hacer fotos...

Lo preparo todo: Nikon d5200, Nikkor 18-200, robot , miro las baterias y en principio tienen carga, lo cojo todo y me desplazo hasta el lugar elejido.

Hace un poco de viento, alineo el conjunto y empiezan las tomas...tengo el tiempo justo debido a otros compromisos, todo parece que va bién hasta que se acaba la bateria de la cámara cuando tenia realizada algo más de la mitad de las tomas. Tengo dos opciones, cancelar o probar de cambiar la bateria. Decido esta segunda opción pero para ello debo aflojar completamente la camara y tengo un riesgo excesivo de que luego no se solapen las imagenes. Y asi lo hice: cambio de bateria y reanudamos el ciclo desde el principio de la linea dónde estaba. Es muy importante antes de empezar con las tomas apuntarse el numero de filas, columnas, diafragma y otros valores empleados, asi si hay que seguir el ciclo después de un problema evitaremos tener otro... El problema que tuve luego es que me equivoque e introduje una columna menos en la segunda parte del proyecto.


Ese dia también se me acabó la bateria de la camara deportiva que me acompaña mientras realizaba un time-lapse del making off. Y para rematar la bateria del telefono movil también se agotó!

En fín que fué un poco un desastre. Una vez en casa logré cuadrar las capturas de la última columna, eliminando las ultimas tomas de cada fila previas, y de este modo el software de pegado AutoPano Giga no tuviera problemas para procesar las 555 capturas que ofrecen una resolución de 9.5 GPx.

Y el resultado aqui esta:  http://gigapan.com/gigapans/151988



Dias mas tarde , decidí realizar otra gigafoto pero con el equipo grande, es decir usando el Sigma Bigmos 150-500 + el teleconversor 1.4x. Aqui ya utilizo el otro robot, más grande y robusto y optimizado para este objetivo. En esta ocasión el sitio a fotografiar fué la Vall de Lord, cerca del pueblo de Sant Llorenç de Morunys (Port del Compte - Lérida).

Dado a que con este objetivo acabo generando una imagen con muchas fotos, me cercioné de tener esta vez todas las baterias bien cargadas antes de salir de casa.

Salí de casa y me desplazé hasta el aparcamiento más cercano, a unos 700 metros del mirador desde realizaría las capturas. Ahora tocaba pasear todo el material de un viaje, es un proceso muy agotador que todo el conjunto pesa... (robot + soporte + objetivo + 2 baterias 12v/7Ah , cuatro herramientas de  supervivéncia, etc... unos 20 kilos quizás...). Una vez allí empecé a montarlo todo. Era un dia soleado con algunas nuves, y no tenia nadie "molestando". Es normal cuando me encuentro a alguién que te ve con el robot que empiece a hacer preguntas del tipo "lo vas a poner en youtube" (si es una foto , no un video!), luego los que preguntan en que canal de la TV va  a salir...nada un chou !



La cosa fué bién, no hubo ningun percance a destacar y aqui teneis el resultado de 2925 capturas y una resolución de 49 GPx.

Os dejo el video del making off...


Y una pequeña captura de pantalla de la foto resultante. Si quereis verla en grande entrad al siguiente link : http://gigapan.com/gigapans/152891



Dias mas tarde, ya en semana santa y con dias libres tenia previsto fotografiar Barcelona, el sitio ya elejido previamente, sus accesos, todo claroy todo a punto en casa. Cojo el coche y empiezo a desplazarme, pero pocos minutos después de salir de casa ya empiezan mis dudas...Barcelona tiene otros handycaps: la nieblilla generada por la brisa del mar y su contaminación que reduce la visión y como que parte de la grácia de las fotografias de detalles es ver detalles lo más nítido posible acabé cancelando el proyecto justo llegando a la capital. Estuve esperando a ver la ciudad para confirmar lo que me esperaba, por lo que media vuelta y de retorno a Manresa. Llegé a mi ciudad al mediodia, momento en que la ciudad esta tranquila de personas ya que el sector comercial permanece cerrado a diferencia de las grandes ciudades , y me planté el la Plaça Sant Domenec.

Monté el robot pequeño en el tripode Manfrotto y empecé con las capturas con la Nikon d5200 + Nikkor 18-200 @200mm. Una detrás de otra y de nuevo otra vez con las visitas pertinentes preguntando. Como que habian personas en movimiento de vez en cuando debia pausar para evitar cortes de cabezas inesperados.

En este caso fueron 850 tomas y algo cerca de 13.7 GPx de resolución final.

Podeis verla en grande en el siguiente link : http://gigapan.com/gigapans/153338


Esta dió guerra a la hora de procesarla debido a que corte un coche, difuminé caras de los niños y reparé pequeñas imperfecciones con el Photoshop. La acción de reparar el coche cortado fué clonando la cartelera publicitaria que hay en la izquierda de la pantalla , "montando" otra unos metros más hacia arriba en sentido de un coche gris. Fué "fácil" el clonarla, el problema es que con una fotografia de este tamaño se acaban generando archivos de unos 100 Gb de peso que cuestan de trabajar, aunque hace pocos dias que una persona me dijo... tampoco es tanto! ignorantes...

Tres dias más tarde, decidí subir al Collbaix, una montañita con vistas a gran parte de la comarca del Bages, aqui también me acompañaria mi robot, el trípode y la cámara deportiva AEE SD19, ya que se trataba de un proyecto atrasado por culpa de la dificultad de subir el material a esta montaña, algo mas de 30 minutos cuesta arriba con un ambiente soleado, y una vez allí unas vistas dignas de quedarse un rato a relajarse o simplemente a descansar. Es una montaña con asiduidad de visitas por lo que decidí subir al mediodia para poder montar los artilugios y evitar encontrar muchas personas en el sitio dónde debería montar el robot.


No hubo ningún percance ni en las tomas ni en el procesamiento de las 608 imagenes que darian una resolución de 11 GPx. Esta fotografia la dediqué a toda la gente que le gustaria subir para ver las vistas que por los motivos que sean no puedan hacerlo y les pique la curiosidad de que es lo que se observa desde allí arriba, para vosotros va!

Os dejo el link de la imagen en grande: http://gigapan.com/gigapans/153421


Y un pequeño video time-lapse con el making off que también deseo que os guste:


Y para terminar el post , otra gigafoto apurando los dias de semana "manta" , esta vez desde Cardona con su castillo medieval en primer plano. Tuve que colocar el trípode como pude en un punto de la montaña en que no me molestara ningún arbol.


 Fueron 468 imagenes y unos 8.5 GPx de resolución. Esta vez también usé los mismos equipos y fué acabar las últimas fotos y oscurecerse el cielo, pero aun llegé al coche sin mojarme después de los 20 minutos de paseada. Si la quereis ver en grande podeis verla en http://gigapan.com/gigapans/153499 


Y este es el primer "paquete" de fotografias que realicé durante primavera y semana Santa, en estos momentos tengo otras por procesar en espera de un nuevo iMac más potente que deseo que fluya aun más rápido que el anterior.




Robot panorámico XS (El programa de Arduino 2 de 2)

Ahora toca explicar la segunda parte del programa del robot panorámico. Ahora es el momento del programa para la slide dolly.

Empoezamos borrando la pantalla y en principio ejecutamos la calibración inicial de ejes. Esta subrutina esta comentada para que no se active ya que para que funcione correctamente hay que montar unos sensores extra para marcar los límites.


Acto seguido llamamos a la subrutina define_modo() ,  programa_limite_recorrido() y la subrutina define_velocidad() que cuando llege el momento ya las explicaré con mas detalle, pero que en resumidas cuentas la primera sirve para elejir si queremos hacer time-lapse, video o un modo joystick. En la segunda subrutina es la encargada de programar los limites mientras que en la tercera definimos la velocidad a la que vamos a mover los motores. También definimos la variable pp con el valor de pdisplay (modo de funcionamiento) . Mágicamente el valor de pdisplay se cambiava sólo y el hecho de definir una variable nueva en este punto sirve para memorizar el valor correctamente.


void slide_dolly(){

lcd.clear();
// calibracion_inicial_ejes();     *********BORRAR
define_modo();
int pp=pdisplay;
programa_limite_recorrido();
define_velocidad();

Acto seguido comprobamos si hemos elejido el modo de time-lapse, si es que si, ejecutaremos la subrutina define_fotos() , define_tiempo(); y acto seguido una vez tengamos ejecutadas estas subrutinas que son las encargadas de definir el número de fotos y el espacio de tiempo entre tomas. A continuación dividimos los pasos totales que hemos definido previamente por el numero de fotos a realizar menos una. Igualmente haremos lo mismo para el segundo eje.

if (pp==0){                            // if modo !=timelapse no demani ni define_fotos ni define_tiempo
define_fotos();

define_tiempo();
pasoX=pasoX/(shot-1);
pasoY=pasoY/(shot-1);
}

Borramos de nuevo la pantalla y nos preparamos para empezar mostrandonos en la pantalla el mensaje de "[ENTER] = Start", acto seguido redondeamos los pasos que se van a mover los diferentes ejes , para ello sumamos +0.4 antes de redondear estos valores, esto lo hago porque se tratan de valores enteros y si tiene que dar 33.7 el arduino entenderia que son 33 pasos enteros , aunque se aproxima más a 34, es por ello que le sumo 0.4 y con eso se convierten en 33.7+0.4=34.1 que una vez redondeado que en 34. En cambio si el valor fuera de 33.4 al sumarle 0.4 quedaria en 33.8 que al ser redondeado por arduino serian 33 igualmente.

Acto seguido provocamos una pausa poniendo la variable a=0 y hasta que no pulsemos select, este valor no cambiará a 1 y estará continuamente en el bucle esperando.


lcd.clear();
lcd.setCursor(1,0);
lcd.print("[ENTER] = Start");
lcd.setCursor(0,1);
for (int k=0 ; k<16; k++){
lcd.print(".");
delay(100);
}
// Convertim pasos amb valor decimal a numero sencer.
/*   el paso X es perillos de convertir ja que el valor pot ser superior a 32k i una int no ho aguanta
pasoX=pasoX+0.4;
pasoXX=(int) pasoX;
pasoX=pasoYY;
*/
pasoY=pasoY+0.4;
pasoYY=(int) pasoY;
pasoY=pasoYY;
xy=pasoX/pasoY;
a=0;                 // provoquem pausa
while(a==0){
if((analogRead(0)/margen)==(select/margen)){ //enter)
a=1;
}
}

Borramos de nuevo la pantalla y depeendiendo del tipo de programa que queramos ejecutar (memorizado en la variable pp) acabaremos ejecutando las subrutinas correspondientes rutina_video_1_eje(),  rutina_video_3_ejes(), rutina_time_lapse() o bién la rutina_joystick(). Una vez ejecutada y finalizada la subrutinas , volverá al menú inicial (el que nos deja elejir el modo de Gigapan o le de Slide_dolly), a excepción de si elejimos el modo joystick que sólo podremos salir de ella forzando un reset a nuestro Arduino.

lcd.clear();
if(pp==1){
rutina_video_1_eje();
}
if(pp==3){
rutina_video_3_ejes();
}
if(pp==0){
rutina_time_lapse();
}
if(pp==4){
rutina_joystick();
}
}

La siguiente subrutina lo único que hace es mostrarnos en la pantalla un mensaje informandonos que se están buscando los limites , empezando primero por el eje X . Para ello va dando impulos en sentido negativo al motor paso a paso hasta que detecta el sensor de origen (limitX) . En el momento que detecte este sensor, el motor avanza 10 pulsos positivos con lo que en principio se espera que el sensor de limite deja de detectar. Una vez tiene el eje X en origen, realizará la misma operación pero en el eje Y siguiendo la misma lógica pero está vez se moverá el motor Y y el límite de posicionamiento vendrá dado por le sensor limitY.

void calibracion_inicial_ejes(){
lcd.setCursor(0,0);
lcd.print("Buscando limites");
lcd.setCursor(0,1);
lcd.print("Eje X");
int a=0;
while(a==0){
if(digitalRead(limitX)==HIGH){  //
a=1;
}
myStepperX.step(-1);
}
delay(300);
myStepperX.step(10);
a=0;
lcd.setCursor(0,1);
lcd.print("Eje Y");
while(a==0){
if(digitalRead(limitY)==HIGH){      //
a=1;
}
myStepperY.step(-1);
}
delay(300);
myStepperY.step(10);
a=0;
}

Ahora es el momento de definir el modo de funcionamiento de nuestra slide dolly mediante la subrutina define_modo(). Empezaremos borrando la pantalla e informando de que estamos en el modo de Slide dolly para confirmarlo. Tras unos segundos nos dejará elejir si queremos hacerla funcionar en modo automático o en modo manual (llamado modo Joystick). 
Mediante el uso de los pulsadores UP & DOWN nos desplazaremos entre estas opciones hasta que no pulsemos Select para validar.La variable pdisplay será la encargada de memorizar la opción elejida en esta parte del programa, pero luego se convierte en variable pp porque se "perdia" el valor mágicamente.


void define_modo(){
lcd.clear();
lcd.print("__Slide__dolly__");
delay(3000);
lcd.clear();
lcd.setCursor(1,0);
lcd.print(">1. Automatico");
lcd.setCursor(2,1);
lcd.print("2. Joystick");


while((analogRead(0)/margen)!=(select/margen)){  // select original era :  while(digitalRead(PinSelect)!=HIGH)
delay(100);
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
pdisplay0=4;
lcd.setCursor(1,1);
lcd.print(">");
lcd.setCursor(1,0);
lcd.print(" ");
}
if((analogRead(0)/margen)==(arriba/margen)){  //arriba
pdisplay=0;
lcd.setCursor(1,1);
lcd.print(" ");
lcd.setCursor(1,0);
lcd.print(">");
}
}

Si hemos elejido el modo Joystick como que no hay nada más que programar, se ejecutará directamente su subrutina especifica, la rutina_joystick() de lo contrarrio nos dejará elejir entre realizar un time-lapse o un video, y también lo elejiremos mediante las teclas UP y DOWN , y de nuevo hasta que no pulsemos la tecla Select podremos dudar que es lo que queremos hacer. Se observa un delay(1000) justo después de aparecer el menú en la pantalla, esto lo hago para que no se validen automaticamente todos los menús por error evitando que se seleccionen las opciones sin querer por tener aun pulsados la tecla Select desde nuestra anterior elección del menú previo. 

if(pdisplay0>=4){
rutina_joystick();
}
//if (pdisplay0==0){
lcd.clear();
lcd.setCursor(1,0);
lcd.print(">1. Time-lapse");
lcd.setCursor(2,1);
lcd.print("2. Continuo");


delay(1000);
while((analogRead(0)/margen)!=(select/margen)){  // select original era :  while(digitalRead(PinSelect)!=HIGH)
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
pdisplay=1;

lcd.setCursor(1,1);
lcd.print(">");
lcd.setCursor(1,0);
lcd.print(" ");
}
if((analogRead(0)/margen)==(arriba/margen)){  //arriba
pdisplay=0;

lcd.setCursor(1,1);
lcd.print(" ");
lcd.setCursor(1,0);
lcd.print(">");
}
}
Serial.println(pdisplay);

a=0;

Si hemos elejido el moto video, nos aparecerá otro menú que servirá para que elijamos si queremos realizar un video con un sólo eje (motor principal de la dolly) o bién deseamos utilizar los 2 ejes. Esta parte del programa es simplemente igual que las dos anteriores comentadas en concepto de programación. 


if(pdisplay==1){          //elejimos 1 o 2 ejes en modo video
lcd.clear();
lcd.clear();
lcd.setCursor(0,0);
lcd.print(">1 = Eje Horizon");
lcd.setCursor(1,1);
lcd.print("2 = Los 2 ejes");
delay(500);
while((analogRead(0)/margen)!=(select/margen)){  // select
delay(100);
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
pdisplay=3;
lcd.setCursor(0,1);
lcd.print(">");
lcd.setCursor(0,0);
lcd.print(" ");
}
if((analogRead(0)/margen)==(arriba/margen)){  //arriba
pdisplay=1;
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print(">");
}
}
}
}

A continuació la secuencia de programación de limites de recorrido: Empezamos con una pausa y acto seguido nos muestra en pantalla un mensaje informandonos que elijamos el punto de inicio del eje X. Acto seguido mediante las teclas LEFT y RIGHT si las pulsamos avanzaremos o retrocederemos el equivalente a 10 pasos de nuestro motor paso a paso. 
En caso de que activaramos el sensor de limite, nos aparecerá un mensaje informandonos que estamos en el límite. Podremos mover el carro hasta dónde queramos hasta que no pulsemos la tecla Select, para ello en el inicio de esta subrutina se define el valor de a=0 y para provocar el bucle lo logramos mediante la instrucción while(a==0).
Otra cosa que no he comentado, es que cuando pulsamos cualquier botón lo que hacemos es leer el valor de la entrada análogica0 y la dividimos del valor margen, este sirve para dar una tolerancia de error, cuanto más grande sea el valor margen , mayor será la tolerancia de nuestro pulsador pero no es conveniente que sea muy grande , no sea que se solapen dos valores muy parecidos y luego nuestro Arduino haga lo primero que le parezca...

void programa_limite_recorrido(){
//a=0;
delay(1000);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Elije punto de");
lcd.setCursor(0,1);
lcd.print("inicio del eje X");          //buscar punto INICIO de la dolly eje X


delay(200);
while(a==0){
if((analogRead(0)/margen)==(select/margen)){ //enter)
a=1;
}
delay(15);
if((analogRead(0)/margen)==(right/margen)) {   //  derecha +X
myStepperX.step(10);  
}
if((analogRead(0)/margen)==(left/margen)) {   //  izquierda -X
for (int i = 0; i<10; i++){
if(digitalRead(limitX)==HIGH){
lcd.setCursor(0,1);
lcd.print("ATENCION LIMITE!");
}else{
myStepperX.step(-1);
}
}
}
}

Una vez hallado el punto de inicio del eje X haremos lo mismo pero para el punto final. La lógica usada será la misma que la utilizada para buscar el punto de inicio pero con una pequeña diferencia: ahora memorizaremos en lal variable pasoX  los pasos que realice el motor cuando nosotros lo estamos posicionando. Este valor nos lo irá mostrando continuadamente en la pantalla.


a=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Busca punt final");
lcd.setCursor(3,1);
lcd.print("del eje X:");          //buscar el punto FINAL de la dolly eje X


while(a==0){
if(((analogRead(0)/margen)==(select/margen))&(pasoX!=0)){        
a=1;
}
if((analogRead(0)/margen)==(right/margen)) {   //  derecha +X
if (pasoX<20000){
pasoX=pasoX+10;
myStepperX.step(10);
lcd.setCursor(3,1);
lcd.print("   ");
lcd.setCursor(6,1);
lcd.print(pasoX);
lcd.print("     ");
}
}
if((analogRead(0)/margen)==(left/margen)) {   //  izquierda -X
if(digitalRead(limitX)==HIGH){
lcd.setCursor(0,1);
lcd.print("ATENCION LIMITE!");
}else{
pasoX=pasoX-10;
myStepperX.step(-10);
}
lcd.setCursor(3,1);
lcd.print("   ");
lcd.setCursor(6,1);
lcd.print(pasoX);
lcd.print("     ");
}
}

A continuación realizaremos lo mismo pero para el eje Y. Empezaremos buscando el punto inicial en pasos de 50 pulsos, este valor lo podeis modificar a vuestro gusto. Y una vez obtenido este, buscaremos elpunto final del eje Y memorizando la posición  mediante la variable PasoY.


if (pdisplay==1){
a=1;
}else{
a=0;
delay(1000);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Elije punto de");
lcd.setCursor(0,1);
lcd.print("inicio del eje Y");          //buscar punto INICIO de la dolly eje Y
delay(200);
}
while(a==0){
if((analogRead(0)/margen)==(select/margen)){ //enter)
a=1;
}
delay(15);
if((analogRead(0)/margen)==(right/margen)) {   //  derecha +Y
myStepperY.step(5);
}
if((analogRead(0)/margen)==(left/margen)) {   //  izquierda -Y
myStepperY.step(-5);
}
}
if (pdisplay==1){
a=1;
}else{
a=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Busca punt final");
lcd.setCursor(3,1);
lcd.print("del eje Y:");          //buscar el punto FINAL de la dolly eje Y


delay(500);
}
while(a==0){

Originalmente con la siguiente instrucción forzaba a que el punto final fuera diferente del inicial, simplemente porque cuando luego habia que buscar la proporción de pasosX respecto Y, si este último valor era 0 la división era infinito provocando un error con repercusiones desconocidas. Si quereis modificar esta linea solo teneis que incluir el &(pasoY!=0) y organizar corchetes.

if(((analogRead(0)/margen)==(select/margen))){   //original &(pasoY!=0)

a=1;
}
delay(15);
if((analogRead(0)/margen)==(right/margen)) {   //  derecha +X
if (pasoY<3200){
pasoY=pasoY+5;
myStepperY.step(5);
lcd.setCursor(3,1);
lcd.print("   ");
lcd.setCursor(6,1);
lcd.print(pasoY);
lcd.print("     ");
}
}
if((analogRead(0)/margen)==(left/margen)) {   //  izquierda -X
pasoY=pasoY-5;
myStepperY.step(-5);
lcd.setCursor(3,1);
lcd.print("   ");
lcd.setCursor(6,1);
lcd.print(pasoY);
lcd.print("     ");
}
}

A continuación se colocan los motores en su posición de inicio , es tan fácil como forzar el movimiento de cada uno de los dos motores para que actuen los pasos programados anteriormente pero en sentido inverso. Primero empezamos con el motor X y luego con el Y.

// desplazamos hasta el origen eje X
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Mueve a origen");
lcd.setCursor(5,1);
lcd.print("Eje X");


myStepperX.step(-pasoX);

Una manera muy tonta de tener claro el sentido de trabajo de cada motor es cuestionandonos si el valor de pasos es positivos o negativos. Ahora cuando aun no se ha movido ningun motor es fácil, el problema vendrá luego mas tarde, una vez hechas las proporciones de pasoX/pasoY si ambas son negativas se convierte el resultado positivo todo y aqui es cuando hay que tener una memoria para que en todo momento quede claro el sentido si no queremos enviar la dolly a casa del vecino.

if (pasoX>0){
sentidoX=0;
}else{
sentidoX=1;
}

lcd.setCursor(5,1);
lcd.print("Eje Y");
myStepperY.step(-pasoY);
if (pasoY>0){
sentidoY=0;
}else{
sentidoY=1;
}
}

En la siguiente subrutina define_fotos() tal y como dice su nombre sirve para que programemos el número de fotos a realizar, en principio ya viene pre-definida como 25 fotos, pero si vais a hacer un time-lapse de varios segundos necesitareis unas cuantas mas. Tened en cuenta que son necesarias 25 imagenes por segundo como mínimo para que nuestro video de time-lapse tenga un refresco de imagen aceptable . En principio está capado a una capacidad de 250 capturas pero si buscais en las siguientes lineas, vereis que es muy fácil modificarlo/eliminar esta opción.

Utilizo la misma lógica de siempre: se declara la variable a=0 y luego hay un while que viene a decir "mientras a sea 0 ves haciendo el bucle" . Para salir del bucle hay que pulsar Select y automaticamente cambiará el valor de a=1 y acto seguido saldremos del bucle.

Dentro del bucle si pulsamos UP incrementamos una foto y si pulsamos DOWN decrementamos una foto.

También hay unas lineas dónde miramos el valor de fotos (variable shot) que si es superior a un valor quita o pone espacios en blanco en nuestro lcd antes de mostrar el valor, esto lo hago para que quede todo mas pulido, esta es una de las partes más pesadas, hacerlo que quede bonito en nuestra pantalla dentro de las limitadas posibilidades que nos ofrece.


void define_fotos(){
a=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Numero de fotos");
lcd.setCursor(4,1);
lcd.print(shot,1);
lcd.setCursor(6,1);
lcd.print(" fotos");
delay(200);
while(a==0){
if((analogRead(0)/margen)==(select/margen)){ //enter)
a=1;
}
delay(150);
if((analogRead(A0)/margen)==(arriba/margen)) {   //  arriba
if (shot<250){
shot=shot+1;
lcd.setCursor(3,1);
if (shot<100){
lcd.print(" ");
}
if (shot<10){
lcd.print(" ");
}
lcd.print(shot);
lcd.setCursor(6,1);
lcd.print(" fotos");
}
}
if((analogRead(A0)/margen)==(abajo/margen)) {   //  abajo
if (shot>1){
shot=shot-1;
lcd.setCursor(3,1);
if (shot<100){
lcd.print(" ");
}
if (shot<10){
lcd.print(" ");
}
lcd.print(shot);
lcd.setCursor(6,1);
lcd.print(" fotos");
}
}
}
}

En la siguiente subrutina define_tiempo() sirve para determinar el tiempo entre fotos de nuestro time-lapse, sigue la misma lógica de la subrutina de define_fotos, pero esta vez la variable a memorizar es segundos_secuencia.


void define_tiempo(){
a=0;
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Define  tiempo");
lcd.setCursor(2,1);
lcd.print("entre  fotos");

delay(1000);
while(a==0){
if((analogRead(0)/margen)==(select/margen)){ //enter)      
a=1;
}
delay(150);
if((analogRead(0)/margen)==(arriba/margen)){  //arriba
if (segundos_secuencia<250){
segundos_secuencia=segundos_secuencia+1;
lcd.setCursor(0,1);
lcd.print("    ");
if(segundos_secuencia<100){
lcd.print(" ");
}
if(segundos_secuencia<10){
lcd.print(" ");
}
lcd.print(segundos_secuencia);
lcd.setCursor(7,1);
lcd.print(" seg.  ");
}
}
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
if (segundos_secuencia>1){
segundos_secuencia=segundos_secuencia-1;
lcd.setCursor(0,1);
lcd.print("    ");
if(segundos_secuencia<100){
lcd.print(" ");
}
if(segundos_secuencia<10){
lcd.print(" ");
}
lcd.print(segundos_secuencia);
lcd.setCursor(7,1);
lcd.print(" seg.  ");
}
}
}
}

En la siguiente subrutina sirve para definir la velocidad de los ejes. Es una función que he probado poco, lo siento, no tengo tanto tiempo como me gustaria! Basicamente sigue la misma lógica que las subrutinas anteriores en cuanto a control de pulsadores y la variable a tratar es velocidadX, mediante el programa múltiplicamos este valor por 2.5, de esta manera si queremos llegar al 100% de velocidad , el valor real será 40.

void define_velocidad(){
a=0;
velocidadX=10;
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Velocidad Ejes");
lcd.setCursor(5,1);
lcd.print(velocidadX*2.5);
lcd.print(" %  ");
delay(500);
while(a==0){
if((analogRead(0)/margen)==(select/margen)){ //enter)
a=1;
}
delay(150);
if((analogRead(0)/margen)==(arriba/margen)){  //arriba
if (velocidadX<40){
velocidadX=velocidadX+1;
}
lcd.setCursor(5,1);
lcd.print(velocidadX*2.5);
lcd.print(" %  ");
}  
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
if(velocidadX>1){
velocidadX=velocidadX-1;
}
lcd.setCursor(5,1);
lcd.print(velocidadX*2.5);
lcd.print(" %  ");
}
}


Una vez confirmada nuestra selección igualamos el valor en las velocidades de ambos ejes y la aplicamos mediante las funciones myStepper?.setSpeed(velocidad)

velocidadY=velocidadX;
myStepperX.setSpeed(velocidadX);      // definimos velocidad impulsos motor
myStepperY.setSpeed(velocidadY);      // definimos velocidad impulsos motor

}

A por la rutina de video de 1 eje ! Empezamos haciendo una limpieza de pantalla y nos aparecerá en pantalla un mensaje informandonos que vamos a grabar, y un segundo y medio después se activará la señal de remoto de nuestra cámara. Acto seguido en la pantalla nos mostrará el % de velocidad a que se va a realizar . Si durante la grabación pulsamos UP o DOWN modificaremos esta velocidad.

void rutina_video_1_eje(){        //rutina video
lcd.clear();
lcd.setCursor(0,0);
lcd.print("A T E N C I O N");
lcd.setCursor(0,1);
lcd.print("Grabando video");
delay(1500);
digitalWrite(PinShot, HIGH);
delay(1000);
if(pasoX<0){
pasX=-pasoX;
}else{
pasX=pasoX;
}

En vez de ejecutar con una sola instrucción el movimiento realizando todos los pasos de golpe, realizamos el movimiento paso a paso y verificamos continuamente que no excedamos de la posición de los micros de seguridad. El programa esta preparado, pero no lo tengo implementado y lógicamente no está probado!

for (int i = 0; i<pasX; i++) {
if(digitalRead(limitX)==HIGH){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("ATENCION LIMITE");
delay(10000);
i=pasX;
break;
}else{

Aqui es dónde podemos modificar el valor de velocidad. El hecho de hacer mover el motor paso a paso también sirve para que podamos realizar pequeñas actuaciones como esta , si definieramos todo el movimiento de golpe no podriamos cambiar la velocidad a media trayectoria. Comentar que si entre las instrucciones de movimiento de un paso de motor hasta que se repite si hay muchas instrucciones que aunque sean "tontas" nos frena el programa y podemos provocar que vaya a golpes. Sobretodo instrucciones de visualización en nuestra LCD nos puede provocar este problema. El pobre Arduino le falta velocidad de procesamiento y de tratamiento de datos.

if((analogRead(0)/margen)==(arriba/margen)){  //arriba
if (velocidadX>2 && velocidadX<40){
velocidadX=velocidadX+1;

myStepperX.setSpeed(velocidadX);      // definimos velocidad impulsos motor
}
}
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
if (velocidadX>2 && velocidadX<40){
velocidadX=velocidadX-1;

myStepperX.setSpeed(velocidadX);      // definimos velocidad impulsos motor
}
}
if (sentidoX==1){
myStepperX.step(-1);
}else{
myStepperX.step(1);
}
}
}
delay(200);
digitalWrite(PinShot, LOW);

Una vez recorrido el espacio, en nuestra LCD nos confirmará el fín de la grabación y el carro retornará a la posición de inicio.

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Fin del video");
delay(2000);
lcd.setCursor(0,1);
lcd.print("Retorno a inicio");
myStepperX.setSpeed(10);      // definimos velocidad impulsos motor
myStepperX.step(-pasoX);

lcd.clear();
lcd.setCursor(5,2);
lcd.print("F I N  !");
delay(5000);
}

Vamos a por el video de 2 ejes, este todo y ser casi igual al de 1 eje da mucha guerra... Arduino SÓLO puede ejecutar una acción a la vez y por lo tanto mientras mueve un motor el otro está quieto, es otra de las limitaciones que tiene y que ya he repetido varias veces. Otra cosa es que lo intentemos engañar con pequeños movimientos entre ambos motores y de sensación de que todo va sincronizado...pero ja! Es más , nosotros estamos utilizando motores paso a paso y confiamos en que no se pierda ningún paso por el camino, lo suyo seria tener un encoder o aunque fuera muy guarro un potenciometro variable para tener medio controlada la posición de nuestro invento...

Previamente a este punto hay una línea dónde dice algo asi: xy=pasoX/pasoY que sirve para buscar una proporción de los pasos que va a dar el eje X respecto el Y. Como que el resultado de xy es un valor entero quiere decir que si multiplico xy*pasoY es posible que no de pasoX, y esto es lo que hacemos en la formula dónde definimos el resto. Este valor serán los pasos "perdidos" del eje X.

Para que me entendais mejor, imaginamos que pasoX=1000, pasoY= 220, cuando hacemos xy=pasoX/pasoY , sería 1000/220 = 4.54, como que xy está definido como una int , es un número entero y va a memorizar con valor 4.

Entonces se moveria 4 pasos durante 220 veces el eje X y a cada paso 4 pasos de X se moveria uno de Y, resultado final = nos faltarian 1000-880 pasos = 120 pasos perdidos.

¿ Como lo arreglo? calculo el resto = 120 pasos y lo divido de 2. 

Arrancamos el eje X durante la mitad de pasos del resto (60 pasos) y acto seguido hago la secuendica de 220 veces 4 pasos de X por 1 paso de Y (total 880 pasos de X y 220 de Y). Llegados a este punto llevamos 940 pasos de X y 220 de Y . Ya sólo falta mover el eje X durante la mitad del resto (60 pasos)  para completar todo el recorrido de X y de Y. Si estos "escalones" no os gustan siempre podeis eliminarlos o editar el video...

¿Vaya toston no? Pues es lo que hay! Si a alguién se le ocurre una manera mejor que me la explique!

void rutina_video_3_ejes(){        //rutina video 2 ejes

resto=pasoX-(xy*pasoY);

lcd.setCursor(0,0);
lcd.print("A T E N C I O N");
lcd.setCursor(0,1);
lcd.print("Grabando video");
delay(1500);
digitalWrite(PinShot, HIGH);
delay(1000);


myStepperX.step(resto/2);

if(pasoX<0){
pasX=-pasoX;
}else{
pasX=pasoX;
}
if(pasoY<0){
pasY=-pasoY;
}else{
pasY=pasoY;
}
if(xy<0){       //linies noves
  xy=xy*(-1);
}
// *********************************
   
for (int m = 0; m<pasY; m++) {
for (long int n = 0; n<(xy); n++) {
if(digitalRead(limitX)==HIGH){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("ATENCION LIMITE!");
delay(10000);
n=pasoX;
break;
}else{
if((analogRead(0)/margen)==(arriba/margen)){  //arriba
if (velocidadX>2 && velocidadX<40){
velocidadX=velocidadX-1;
myStepperX.setSpeed(velocidadX);      // definimos velocidad impulsos motor
myStepperY.setSpeed(velocidadX);      // definimos velocidad impulsos motor
}
}
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
if (velocidadX>2 && velocidadX<40){
velocidadX=velocidadX+1;
myStepperX.setSpeed(velocidadX);      // definimos velocidad impulsos motor
myStepperY.setSpeed(velocidadX);      // definimos velocidad impulsos motor
}
}
if (sentidoX==1){
myStepperX.step(-1);
}else{
myStepperX.step(1);
}
}
}
if (sentidoY==1){
myStepperY.step(-1);
}else{
myStepperY.step(1);
}
}

// ***********************************************

myStepperX.step(resto/2);

delay(200);
digitalWrite(PinShot, LOW);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Fin del video");
delay(2000);

Luego después de que se nos muestre el mensaje de "Fín de video" volvemos a inicio y acabamos con nuestra rutina. Lo siento no tengo fotos, mirad el video...




lcd.setCursor(0,1);
lcd.print("Retorno a inicio");

myStepperX.step(-pasoX);

myStepperY.step(-pasoY);

lcd.clear();
lcd.setCursor(5,1);
lcd.print("F I N  !");
delay(10000);
}

Ahora es la hora de la rutina time-lapse, xD ! creo que nunca acabaré este post! Es muy parecido en cuanto a funcionamiento al video de 2 ejes pero no se ha implementado la funcion resto ya que es "tonteria" que se mueva un espacio y luego se descuadre . Dónde hay más trabajo es en la visualización de datos en nuestra LCD.

Empezamos creando una rutina que se repetirá tantas veces como numero de fotos a realizar. Actualizamos valores en pantalla y realizamos una foto mientras el gif cierra el diafragma. 


void rutina_time_lapse(){       //rutina time-lapse
for(int i = 1; i< shot; i++){  
//logo0();
logo2();
lcd.setCursor(0,0);
lcd.print("s:");
lcd.print(i);
lcd.setCursor(7,1);
lcd.print(i*100/shot);
lcd.print("%");
lcd.setCursor(1,1);
lcd.print("F O T O  ! ");
digitalWrite(PinShot, HIGH);
logo2();
delay(300);
digitalWrite(PinShot, LOW);
delay(300);

logo3();
lcd.setCursor(1,1);
lcd.print("M O V E  ! ");
if(pasoX<0){
  pasX=-pasoX;
}else{
  pasX=pasoX;
}
if(pasoY<0){
  pasY=-pasoY;
}else{
  pasY=pasoY;
}

Acto seguido y tras un pequeño retardo de 300 mS se mueve la dolly paso a paso en el eje X verificando que no exista contacto con el sensor de limite del ejeX, luego moverá el ejeY.

for (int i = 0; i<pasX; i++) {
if(digitalRead(limitX)==HIGH){
lcd.setCursor(0,1);
lcd.clear();
lcd.print("ATENCION LIMITE!");
delay(10000);
i=pasX;
break;
}else{
if (sentidoX==1){
myStepperX.step(-1);
}else{
  myStepperX.step(1);
}
}
}
for (int i = 0; i<pasY; i++) {
if (sentidoY==1){
myStepperY.step(-1);
}else{
  myStepperY.step(1);
}
}
lcd.setCursor(0,1);
lcd.print("           ");
lcd.setCursor(7,1);
lcd.print(i*100/shot);
lcd.print("%");

posicion_actual_X=(posicion_actual_X+pasoX);
posicion_actual_Y=(posicion_actual_Y+pasoY);

Mientras está efectuando el retardo entre fotos podemos incrementar este retardo mediante las teclas UP y DOWN, si pulsais UP al incrementar el valor os va a parecer que no haceis nada, pero a cada decima de segundo le estais incrementando una más , y os dareis cuenta en la siguiente "pausa". Si por el contrario pulsais DOWN decrementais este valor

Si por el contrario pulsais SELECT provocaremos una pausa.

for (int j=0; j<(segundos_secuencia*10); j++){  
if((analogRead(0)/margen)==(arriba/margen)){  //arriba
segundos_secuencia=segundos_secuencia+0.1;
}
if((analogRead(0)/margen)==(abajo/margen)){   //abajo
segundos_secuencia=segundos_secuencia-0.1;
}
delay (100);
lcd.setCursor(0,1);
tiempo_reloj=j*0.1;
if ((segundos_secuencia-tiempo_reloj)<10){
lcd.print(" ");
}
lcd.print(segundos_secuencia-tiempo_reloj);
lcd.setCursor(4,1);
lcd.print(char(34));
lcd.print(" ");
lcd.setCursor(6,0);
lcd.print("X:");
lcd.print(posicion_actual_X,0);
tempi=i;
peticiopausadolly();
/*
lcd.setCursor(6,2);
lcd.print("Y:");
lcd.print(posicion_actual_Y,0);
*/
}
}

Una vez realizadas todos los movimientos nos faltará la última foto para completar, y a continuación ya nos aparecerá el mensaje de MotionLapse completo! Momento en que la dolly retrocederá a su punto de origen.

logo2();
lcd.setCursor(0,1);
lcd.print("     ");
digitalWrite(PinShot, HIGH);
logo3();
delay(500);
digitalWrite(PinShot, LOW);
delay(100);
lcd.clear();
logo2();
lcd.setCursor(0,0);
lcd.print("MotionLapse");
lcd.setCursor(0,1);
lcd.print(" completo!");

myStepperX.step(-posicion_actual_X);
myStepperY.step(-posicion_actual_Y);
delay(5000);
}

La subrutina peticiopausadolly() preguntará diez veces si está el pulsador de SELECT apretado, si sólo pusieramos una, se lo pasaria por el forro.. aqui si que corre el Arduino! Si detecta que esta pulsado entraremos en modo pausa y no saldremos hasta que pulsemos la tecla DOWN, momento en el cual actualizaremos datos de la pantalla y continuaremos (saldremos de la subrutina)

void peticiopausadolly(){
for (int k=0; k<10; k++){ //prova pausa
if((analogRead(0)/margen)==(select/margen)){     // tecla SELECT si apretem provoquem una pausa fins que no apretem ENTER
lcd.clear();
lcd.setCursor(2,0);
lcd.print("P a u s a  !  ");
lcd.setCursor(0,1);
lcd.print("[DOWN] = reStart");
delay(1000);  //abans no hi era i em rearrancaba
pause=2;
while(pause>1){
if((analogRead(0)/margen)==(abajo/margen)){  //abajo
pause=0;
lcd.clear();
logo2();
lcd.setCursor(0,0);
lcd.print("s:");
lcd.print(tempi);
lcd.setCursor(7,1);
lcd.print(tempi*100/shot);
lcd.print("%");
}
}
}
}
}

La subrutina joystick nos servirá para mover manualmente nuestra dolly/robot mediante los pulsadores UP, DOWN, LEFT y RIGHT , y realizar capturas cada vez que pulsemos el botón SELECT.
Para salir de esta subrutina hay que forzar un reset a nuestro Arduino.
Creo que si habeis entendido el resto de programa, aqui ya no hace falta ninguna explicación mas, simplemente es mas de lo mismo.


void rutina_joystick(){
a=0;
while(a==0){
myStepperX.setSpeed(3);      // definimos velocidad impulsos motor
myStepperY.setSpeed(3);      // definimos velocidad impulsos motor
lcd.clear();
lcd.setCursor(1,0);
lcd.print("MODO  JOYSTICK");
delay(500);

while(pdisplay!=99){
if((analogRead(0)/margen)==(right/margen)){   //derecha +X
myStepperX.step(5);
pasoX=pasoX+1;
}
if((analogRead(0)/margen)==(left/margen)){   //izquierda -X
myStepperX.step(-5);
pasoX=pasoX-1;
}

if((analogRead(0)/margen)==(arriba/margen)){   //arriba +Y
myStepperY.step(5);
pasoY=pasoY+1;
}

if((analogRead(0)/margen)==(abajo/margen)){   //abajo -Y
myStepperY.step(-5);
pasoY=pasoY-1;
}

if((analogRead(0)/margen)==(select/margen)){ //enter)
digitalWrite(PinShot, HIGH);
lcd.setCursor(0,1);
lcd.print("   F O T O  !");


delay(500);
digitalWrite(PinShot, LOW);
lcd.setCursor(0,1);
lcd.print("             ");
delay(500);
}
lcd.setCursor(1,1);
lcd.print("X: ");
lcd.print(pasoX);
lcd.print("  ");
lcd.setCursor(9,1);
lcd.print("Y: ");
lcd.print(pasoY);
lcd.print("  ");
}
}
}

Finalmente implementé la subrutina reset para poner todos los registros de valores a 0 para que una vez realizadas cualquier secuencia y fueramos a hacer otra no aparecieran movimientos ilógicos. Simplemente hay una re-definición de los valores de todas las variables.

void reset(){
progreso=0;
pasoX=0;
pasoY=0;
xact=0;               // º actual eje X
yact=0;               // º actual eje Y
xmax=0;               // º posición máxima eje X
xmin=0;               // º posición mínima eje X
ymax=0;               // º posición máxima eje Y
ymin=0;               // º posición mínima eje Y
xtemp=0;
ytemp=0;
nshot=0;
columnasX=0;                 // número de filas eje X >> (xmax-xmin)/pasoX
columnasXX=0;
filasY=0;              // número de columnas eje Y    >> (ymax-ymin)/pasoY
filasYY=0;
previsionShot=0;          // prevision número shots   columnasX * filasY
segundos=0 ;
minutos=0 ;
horas=0 ;
pause=0;
pdisplay=0;
pdisplay0=0;
valorTempX=0;
valorTempY=0;
progreso=1;
solape=0.20;
retardo=0;
origen=0;
tempj=0;
tempi=0;
a=0;
sentidoX=0;
sentidoY=0;
shot=25;
pasoXX=0;              // valor temporal dolly eje X
pasoYY=0;              // valor temporal dolly eje Y
pasX=0;
pasY=0;
xy=0;
resto=0;
segundos_secuencia=3;
posicion_actual_X=0;
posicion_actual_Y=0;
velocidadX=0;
velocidadY=0;
tiempo_reloj=0;
espai=0;
paso=0;
menu=2;
menu0=0;
modenight=2;
factor=1.5;     // en su defecto : FF = 1, Nikon DX=1.5 , Canon DX=1.6 , Olympus= 2
focal = 200;

}

Y se acabó por hoy ! Reconozco que hay varios puntos a mejorar, se aceptan ayudas jiji! Y no sé cuantos post tengo pendientes de publicar...pero es que me gusta compartirlos pero faltan horas!

Si quereis todo el programa completo, no dudeis en escribirme.

Saludos!

domingo, 11 de mayo de 2014

Lo que dura dura (Batería)

Utilizo una Nikon d5200 para realizar mis inventos, es mi cámara de batalla con la que realizo las Gigafotografías panorámicas. Esta cámara va equipada con una bateria EN-EL14 que subministra unos 7.4 voltios y un puñadito de miliAmperios suficientes para realizar unas teóricas 600 capturasas, pero todo depende de si utilizamos mucho la pantalla, el estabilizador, el auto-focus, el flash... por lo que esas 600 teóricas tomas son muy relativas.

Yo he logrado realizar algo más de 800 capturas trabajando con enfoque manual , y eliminando por completo todo el tema pre-visualizaciones y evitando al máximo esos consumos citados.

A veces uno sale de casa con las baterías que están en principio a tope pero por lo que sea no lo están, o bién simplemente realizas unas tomas previas, previsualizas , juegas con los menús y luego a fotografiar en serio, resumen que ya no están al 100%.

En los dos últimos meses me he encontrado dos veces a 3/4 partes de una Gigapanorámica que me quedo sin batería y en mi último robot para cambiar la misma debo desmontar la cámara. Si debo aflojar el tornillo que fija la cámara hay un riesgo muuuuuy grande de que pierda un poco la posición, lo suficiente para que luego el acoplamiento no sea correcto a la hora de procesarlas. También puede pasar que con esos minutos "perdidos" se muevan las nuves o algun elemento móvil. Tenia la opción de hacer un agujero en la base dónde se aploma la cámara para poder cambiar la batería en cualquier momento, pero ... ¿no será más práctico olvidarse de la batería?

Es por ello que empecé a investigar por el Google ya que sabia que estas cámaras son un poco pejigeras con las baterías y si no le pones una "codificada" se bloquea la cámara.


Nota> Si utilizais un grip para alimentar la cámara mientras una de las dos baterias sean "codificadas" no hay problemas de funcionamiento. El hecho de "codificar" basicamente consiste en la existencia de una pequeña comunicación bateria<=>cámara tal y como explican en el siguiente post de NikonHacker.

Tras ver esta información decidí jugarmela, entendiendo que aparte de la electrónica hay una batería pura y dura y esta es la parte de que yo quería prescindir por lo que cojí una batería clónica (codificada) y haciendo un poco de palanca con un cuchillo de cocina puntiagudo fuí abriendola poco a poco hasta encontrarme con las tripas como se dice bulgarmente.


Tal y como vemos se trata de dos baterias de 3.7V seriadas lo que dan un voltage de 7.4v. Lo curioso es que sale un conductor en el punto de union de ambas por lo que a nuestra placa electrónica también tendrá una señal de 3.7v que deduzco que será usada para hacer trabajar la lógica de la comunicación a 3.3v . 


Mediante el uso del voltimetro confirmo los voltajes y polaridad aunque en la propia placa viene marcado como +B y -B . Una vez todo claro y con el uso de unas alicates de corte rompo los tres conductores para liberar la batería de la electrónica.

Ahora es cuando cojo un step-down de los que hay que comprar en eBay  pues en las tiendas de electrónica de este pais no saben ni lo que es! Se trata de un regulador de voltaje altamente eficiente pues no pierde energía como los 78xx ya que no disipa apenas calor.  Lo conecto a una fuente de alimentación externa para regular el voltaje de sálida al mismo valor que me dá cuando conecto el voltímetro a los bornes positivo y negativo de la batería original (en mi caso unos 7.8v marca el display, pero vosotros haced las pruebas correspondientes, yo me la juego con mis equipos, y aquí cada uno que sea consciente de lo que hace).

Como que en el sistema original habia una toma de tensión que tenia la mitad del voltaje, decido aplicar la ley de ohm y hacer un divisor de tensión, para ello usaremos dos resistencias, las dos que encontré primero fueron de 10 k y lo conectaremos tal y como está el siguiente esquema:


Soldamos los cables a la sálida de nuestro step down al igual que las dos resistencias unidas en su extremo entre si. En este punto es dónde obtendremos la mitad del voltaje.



Una vez comprobado que los voltajes sean apropiados sólo queda soldar estos tres cables a la placa electrónica de nuestra batería.


Ahora haremos un pequeño agujero a la carcasa de nuestra antigua batería para poder sacar el cable. Yo he utilizado un cable de portero automático de 3 x 0.5mm


Ya sólo falta ensamblar y probar. Tal y como veis en la siguiente foto aparecen unos terminales en la bateria marcados como T y D que son los encargados de la comunicación.


Finalmente os dejo un pequeño video demostrativo, grabado como he podido pues me faltaban manos jiji! . Yo aun no he tenido la posibilidad de hacer una prueba de campo con centenares de fotografías pero estoy convencido que funcionará.


Como anécdota deciros que a mi me falló la primera vez y no entendía el porqué, lo más preocupante pasaba por pensar si habría frito la cámara pero tras colocar una batería buena observé que funcionaba bién. Luego con paciencia y con la ayuda del téster fuí analizando hasta encontrar que me fallaba la pista del negativo por lo que acabé realizando un puente (cablecito amarillo) casi directo tal y como veréis en la siguiente foto.


Deseo que os guste y os sirva de algo. 
Saludos y DIY !