Dúvida ligação máquina fotográfica DSLR ao Arduino

Uma nota...

Tirar fotos a gotas não me excita... já isto:

Já tinha visto o pinout do conector que liga à máquina e o tal disparador remoto que tenho é igual ao do teu primeiro link do ebay,portanto não tenho dúvidas aí,só não estou a ver é como vou saber a correspondência correta do conector para a ficha jack estéreo macho,na outra ponta do cabo.

Tenho dois flah's,um Nikon SB-900 e um SB-700,mas como vou começar apenas com um,vou optar pelo SB-900 pelo facto de ter uma ficha PC Sync incorporada para ligar o cabo que o SB-700 não tem (este,além do cabo,é necessário um Hot Shoe com ficha PC Sync).

Quanto a deixar que a máquina controle o disparo do flash,não me parece a melhor solução porque fico muito limitado e talvez não consiga aquilo que pretendo,passo a explicar:a máquina só permite disparar o flash à primeira ou à segunda cortina,ou seja,logo após a abertura do obturador ou imediatamente antes do fecho do obturador,mas eu quero controlar o timing certo para que ele dispare (colisão entre duas gotas,por ex.) pois no fundo vai ser o clarão emitido pelo flash que vai congelar a acção e não o tempo de exposição (obturador aberto)

Isto pode parecer confuso,mas no fundo é uma questão de timing certo já que tudo se desenvolve num espaço de tempo na ordem dos milissegundos e mesmo utilizando a velocidade máxima que a minha (nossa :smiley: ) máquina permite (1/4 000 segundos) não é suficiente para congelar o movimento.

Acho que era preferível controlar apenas o flash e a válvula com o Arduino e fotografar ás escuras com a velocidade de obturador definida como Bulb (abre o obturador quando carregas no botão do obturador e só fecha quando largares) ou mesmo definir 2-3 segundos e deixar que o clarão emitido pelo flash congele o movimento no timing certo,isto com o SB-900 na potência mínima (é mesmo mínima) resulta num clarão que dura aproximadamente 1/40 000 segundos,uma velocidade 10x maior que a permitida pela máquina.
Para perceberes melhor isto das velocidades do flash,vê aqui: Capability of flash units for high speed photography

O controlador da Cognysis (também têm um sistema para líquidos) é muito bom,mas também é muito caro e eu não ganho nada com a fotografia,antes pelo contrário :smiley: Com os teus conhecimentos podes meter mãos à obra e fazer um parecido :slight_smile:

Concordo que fotografar uma simples gota de água não é nada de mais,mas eu queria elevar um pouco a fasquia...Já ouviste falar do Markus Reugels? Dá uma espreitadela: Markus Reugels | Flickr

Resumindo,acho que tenho tudo o que preciso para meter mãos à obra menos os cabos e a válvula,por falar em válvula,que acham deste circuito:

Vou seguir o teu conselho e vou tentar montar o hardware com leds e começar a escrever código para ver no que dá e depois viro-me para a interface.Uma dúvida,como não tenho a válvula,posso testar o funcionamento do circuito com led?

Pedro_Silva:
Já tinha visto o pinout do conector que liga à máquina e o tal disparador remoto que tenho é igual ao do teu primeiro link do ebay,portanto não tenho dúvidas aí,só não estou a ver é como vou saber a correspondência correta do conector para a ficha jack estéreo macho,na outra ponta do cabo.

Multimetro... Eventualmente vais querer cortar o jack estéreo e usar os fios para garantir que não tens problemas de ligações.

Pedro_Silva:
Quanto a deixar que a máquina controle o disparo do flash,não me parece a melhor solução porque fico muito limitado e talvez não consiga aquilo que pretendo,passo a explicar:a máquina só permite disparar o flash à primeira ou à segunda cortina,ou seja,logo após a abertura do obturador ou imediatamente antes do fecho do obturador,mas eu quero controlar o timing certo para que ele dispare (colisão entre duas gotas,por ex.) pois no fundo vai ser o clarão emitido pelo flash que vai congelar a acção e não o tempo de exposição (obturador aberto)

Isto pode parecer confuso,mas no fundo é uma questão de timing certo já que tudo se desenvolve num espaço de tempo na ordem dos milissegundos e mesmo utilizando a velocidade máxima que a minha (nossa :smiley: ) máquina permite (1/4 000 segundos) não é suficiente para congelar o movimento.

Ok... colisão entre duas gotas? Como assim?

Tu obviamente já pesquisaste isto... eu não, e o que dizes faz sentido.

Pedro_Silva:
Acho que era preferível controlar apenas o flash e a válvula com o Arduino e fotografar ás escuras com a velocidade de obturador definida como Bulb (abre o obturador quando carregas no botão do obturador e só fecha quando largares) ou mesmo definir 2-3 segundos e deixar que o clarão emitido pelo flash congele o movimento no timing certo,isto com o SB-900 na potência mínima (é mesmo mínima) resulta num clarão que dura aproximadamente 1/40 000 segundos,uma velocidade 10x maior que a permitida pela máquina.
Para perceberes melhor isto das velocidades do flash,vê aqui: Capability of flash units for high speed photography

Sim, faz sentido. Se os números estiverem correctos. Mas então, para que queres controlar a máquina? A luz vai definir tudo com esta estratégia. Então apenas tens de controlar os flashs e a gota.

Pedro_Silva:
Concordo que fotografar uma simples gota de água não é nada de mais,mas eu queria elevar um pouco a fasquia...Já ouviste falar do Markus Reugels? Dá uma espreitadela: Markus Reugels | Flickr

Não gosto. :\

Pedro_Silva:
Resumindo,acho que tenho tudo o que preciso para meter mãos à obra menos os cabos e a válvula,por falar em válvula,que acham deste circuito:

Sim, isso funciona para a válvula. Nota que a válvula não vai funcionar (ou dificilmente) com 5V do Arduino. Logo vais precisar duma fonte externa. Dito isto, se meteres um optoacoplador a activar a válvula será muito mais seguro.

Pedro_Silva:
Vou seguir o teu conselho e vou tentar montar o hardware com leds e começar a escrever código para ver no que dá e depois viro-me para a interface.Uma dúvida,como não tenho a válvula,posso testar o funcionamento do circuito com led?

Sim. Podes testar tudo com LEDs.

Algumas dicas:
NÃO USES O DELAY!!! ISSO NÃO SERVE PARA O QUE QUERES.
O millis ou micros talvez resultem... mas se usares os timers internos consegues resultados mais rápidos (pode não ser necessariamente o que pretendes).
Não uses o digitalWrite.
Pensa se pretendes ter um interface série ou um interface de botões e um LCD... Um interface série talvez seja mais simples de implementar... mas por outro lado é pior para usar. E tens de ter o computador por perto... o que estraga o plano da escuridão.

Com teclas ou uma espécie de encoder talvez seja simples de fazer isto. Uns quantos botões para escolher a variável que pretendes alterar... talvez diferentes modos de disparo...

Mas ainda falta muito para isso ficar pronto.

bubulindo:
Multimetro... Eventualmente vais querer cortar o jack estéreo e usar os fios para garantir que não tens problemas de ligações.

Se ligar os fios directamente não há problema?

bubulindo:
Ok... colisão entre duas gotas? Como assim?

Algo deste género,são colisões entre duas ou mais gotas: http://www.google.pt/search?hl=pt-PT&q=water+drop+collision&bav=on.2,or.r_qf.&bvm=bv.45645796,d.d2k&biw=1366&bih=606&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&ei=Iqx6UfSgDKir7AaQx4HYDw

bubulindo:
Sim, faz sentido. Se os números estiverem correctos. Mas então, para que queres controlar a máquina? A luz vai definir tudo com esta estratégia. Então apenas tens de controlar os flashs e a gota.

Vejo como vantagem poder controlar a máquina,o facto de poder ir apertando o tempo de exposição à medida que vou afinando o sistema e isso vai-me permitir trabalhar com mais luz ambiente.Outra vantagem é não ter que me preocupar em estar sempre com o comando na mão para abrir e fechar o obturador,o sistema fica mais autónomo,digámos.Mas é perfeitamente possível fazer o que quero sem controlar a máquina,o preço será trabalhar na escuridão.

bubulindo:
Não gosto. :\

Gostos não se discutem,mas dá para ter uma ideia do que pretendo.

bubulindo:
Sim, isso funciona para a válvula. Nota que a válvula não vai funcionar (ou dificilmente) com 5V do Arduino. Logo vais precisar duma fonte externa. Dito isto, se meteres um optoacoplador a activar a válvula será muito mais seguro.

Será uma válvula de 12V alimentada com pilhas...vou estudar a dica do optoacoplador :wink:

bubulindo:
Sim. Podes testar tudo com LEDs.

Algumas dicas:
NÃO USES O DELAY!!! ISSO NÃO SERVE PARA O QUE QUERES.
O millis ou micros talvez resultem... mas se usares os timers internos consegues resultados mais rápidos (pode não ser necessariamente o que pretendes).
Não uses o digitalWrite.
Pensa se pretendes ter um interface série ou um interface de botões e um LCD... Um interface série talvez seja mais simples de implementar... mas por outro lado é pior para usar. E tens de ter o computador por perto... o que estraga o plano da escuridão.

Com teclas ou uma espécie de encoder talvez seja simples de fazer isto. Uns quantos botões para escolher a variável que pretendes alterar... talvez diferentes modos de disparo...

Posso colocar um led no lugar da válvula para testar?Não estou a ver bem como fazer.

Sem dúvida que é muito mais prático poder operar o sistema através de um LCD com botões e esse será o caminho a seguir...Qual te parece melhor um LCD Shield já com botões ou comprar LCD e botões separadamente e montar à posteriori?Por acaso já tenho um LCD Siheld 16x2...

bubulindo:
Mas ainda falta muito para isso ficar pronto.

Acho que aqui dizes muita coisa :astonished: ainda tenho muita pedra para partir!

Obrigado pela tua disponibilidade em ajudar!

Se queres ver a correspondência entre o pino que liga na máquina e o contacto do Jack usas um multimetro. A que te referes quando dizes ligar os fios directamente?
Em todo o caso, acho que não deves usar o jack e deves usar os fios directamente.

As fotos parecem-me todas iguais. Não leves a mal, mas não vejo distincão entre uma gota a bater na água e várias gotas. No entanto, isso são gostos e não importa para o proposito do projecto.

Ok... Mas se o tempo de abertura da máquina é demasiado grande ao ponto de quereres controlar a exposicão só com o flash, terás sempre de trabalhar no escuro para obteres os resultados que queres. No entanto, teres controlo da abertura pode permitir-te maior flexibilidade... e por mais um contacto, não é nada de extraordinário de se fazer.

12V e pilhas são dois termos que não ligam muito bem... Podes ter problemas de corrente ao tentar activar a válvula. Até porque não vais ter o Arduino alimentado pelo computador (lembra-te que o computador emite luz que pode facilmente estragar a exposicão.

O LCD shield é muito prático de utilizar e tem uma vantagem que é o controlo do backlight do LCD. Ao disparares uma sequência, podes desligar o backlight do LCD, esperar um pouco e iniciar tudo de seguida tendo garantido que estás em escuridão. Uma possibilidade, apesar de gastar mais hardware, até seria ter o Arduino a controlar todo o setup.
Ou seja, tinhas a válvula para soltar gotas, o controlo do flash, controlo do disparo e podias adicionar uma luz externa de 230V controlada por relé que era desligada sempre que quisesses bater a foto. Tu vais precisar duma boa luz para fazer o foco da foto, logo essa funcionalidade facilitaria o processo. Em vez de fazeres o setup, desligares a luz da sala e voltares a ligar depois de terminada a foto.

Se pesquisares na net sobre como ligares LEDs no Arduino, encontras imenso. Não precisas de muito, apenas uma resistência por LED.

Faz um bom plano do que pretendes antes de comecares o software para poderes dividir tudo por funcões.

Este até é um projecto que tem algum interesse para mim... mas não para fotografar gotas. Mais para apanhar os meus gatos... LOL

bubulindo:
Se queres ver a correspondência entre o pino que liga na máquina e o contacto do Jack usas um multimetro. A que te referes quando dizes ligar os fios directamente?
Em todo o caso, acho que não deves usar o jack e deves usar os fios directamente.

OK,já percebi,basta testar a continuidade dos fios.
Quanto a ligar os fios directamente,o que queria dizer era cortar o jack e fazer a ligação dos fios directamente no circuito ficando o cabo sempre ligado e depois era só ligar na máquina...não sei se me faço entender.

bubulindo:
As fotos parecem-me todas iguais. Não leves a mal, mas não vejo distincão entre uma gota a bater na água e várias gotas. No entanto, isso são gostos e não importa para o proposito do projecto.

Acreditas que já tive a mesma opinião que tu?Tive mesmo e continuo a achar que fazer este tipo de imagens continuamente se torna monótono e não é isso que pretendo,o que quero é experimentar coisas novas na fotografia.

De qualquer forma para teres ideia da colisão entre gotas que falei vê estes vídeos: Tropfenfotografie Setup, Aufbau und Technik

bubulindo:
12V e pilhas são dois termos que não ligam muito bem... Podes ter problemas de corrente ao tentar activar a válvula. Até porque não vais ter o Arduino alimentado pelo computador (lembra-te que o computador emite luz que pode facilmente estragar a exposicão.

Então vou ter que procurar outra solução,talvez encontre uma fonte de alimentação barata...

bubulindo:
O LCD shield é muito prático de utilizar e tem uma vantagem que é o controlo do backlight do LCD. Ao disparares uma sequência, podes desligar o backlight do LCD, esperar um pouco e iniciar tudo de seguida tendo garantido que estás em escuridão. Uma possibilidade, apesar de gastar mais hardware, até seria ter o Arduino a controlar todo o setup.
Ou seja, tinhas a válvula para soltar gotas, o controlo do flash, controlo do disparo e podias adicionar uma luz externa de 230V controlada por relé que era desligada sempre que quisesses bater a foto. Tu vais precisar duma boa luz para fazer o foco da foto, logo essa funcionalidade facilitaria o processo. Em vez de fazeres o setup, desligares a luz da sala e voltares a ligar depois de terminada a foto.

Parece-me que estou com um problema com o LCD Shield que comprei,é o modelo 'A' aqui: 16 X 2 LCD Keypad Shield for Arduino - LinkSprite Playgound

È o seguinte,depois de encaixar o LCD no Arduino fico sem acesso ás portas do mesmo...vou ter que encontrar uma solução para isto,tens alguma sugestão?

A ideia de adicionar uma luz externa ao setup é realmente muito bem pensado e interessante!

bubulindo:
Se pesquisares na net sobre como ligares LEDs no Arduino, encontras imenso. Não precisas de muito, apenas uma resistência por LED.

Faz um bom plano do que pretendes antes de comecares o software para poderes dividir tudo por funcões.

Bem acho que está na hora de apresentar algum trabalho,estive a testar com leds e resistências e escrevi um código para ver se consigo aquilo que quero...de notar que nunca programei nenhum Arduino e há 3-4 semanas atrás nem sabia o que isso era,portanto o código que escrevi pode não fazer sentido nenhum,mas aparentemente pelo que observo no funcionamento dos leds,faz aquilo que pretendo.
Segue o código:

//
unsigned long time;

const int pushButton = 13;  //botão de inicio ligado ao pinp 13
const int cameraPin = 10;   //shutter da máquina ligado ao pino 10
const int valvulaPin = 11;  //válvula ligada ao pino 11
const int flashPin = 12;    //flash ligado ao pino 12

//

void setup()
 {
   pinMode(pushButton,INPUT);    //inicia o botão como input
   pinMode(cameraPin,OUTPUT);    //inicia o shutter como output
   pinMode(valvulaPin,OUTPUT);   //inicia a válvula como output
   pinMode(flashPin,OUTPUT);     //inicia o flash como output

    digitalWrite(pushButton,HIGH);   //inicia o programa ao pressionar o botão
    digitalWrite(cameraPin,HIGH);    //abre o obturador no modo bulb
    delay(10);                       //esta pausa é só para garantir que o obturador está completamente aberto
    digitalWrite(valvulaPin,HIGH);   //abre a vávula
    delay(200);                      //tameanho da gota 1
    digitalWrite(valvulaPin,LOW);    //fecha a válvula
    delay(360);                      //pausa para a gota um cair dentro do recipiente
    digitalWrite(valvulaPin,HIGH);   //abre novamente a válvula
    delay(50);                       //tamanho da gota 2
    digitalWrite(valvulaPin,LOW);    //fecha a válvula
    delay(400);                      //pausa pra gota 2 colidir com gota 1
    digitalWrite(flashPin,HIGH);     //dispara o flash
    delay(5);                        //muito pequena pausa
    digitalWrite(flashPin,LOW);      //deliga sinal para flash
    digitalWrite(cameraPin,LOW);     //fecha obturador
     
 }
 
 void loop()
 { 
 Serial.print("Time: ");
 time = millis();
 Serial.println(time);
 delay(1000);
 }

bubulindo:
Este até é um projecto que tem algum interesse para mim... mas não para fotografar gotas. Mais para apanhar os meus gatos... LOL

Muito bom o trocadilho,LOL

Pedro_Silva:
OK,já percebi,basta testar a continuidade dos fios.
Quanto a ligar os fios directamente,o que queria dizer era cortar o jack e fazer a ligação dos fios directamente no circuito ficando o cabo sempre ligado e depois era só ligar na máquina...não sei se me faço entender.

Era isso que eu estava a dizer. O jack fica com maus contactos e não é fácil de meter numa placa.

Pedro_Silva:
Acreditas que já tive a mesma opinião que tu?Tive mesmo e continuo a achar que fazer este tipo de imagens continuamente se torna monótono e não é isso que pretendo,o que quero é experimentar coisas novas na fotografia.

Na boa... como disse, também dá para apanhar os meus gatos. LOL

Pedro_Silva:
Então vou ter que procurar outra solução,talvez encontre uma fonte de alimentação barata...

Isso não será difícil, creio... um bom carregador de telemóveis talvez dê.

Pedro_Silva:
Parece-me que estou com um problema com o LCD Shield que comprei,é o modelo 'A' aqui: 16 X 2 LCD Keypad Shield for Arduino - LinkSprite Playgound

Pois... percebi isso agora. Talvez arranjar um shield que dê para soltar componentes e colocar os fios a sair da parte de trás. Ou usar um mega para teres acesso aos pinos da parte de trás.

Pedro_Silva:
È o seguinte,depois de encaixar o LCD no Arduino fico sem acesso ás portas do mesmo...vou ter que encontrar uma solução para isto,tens alguma sugestão?

Podes também pesquisar por uns LCDs que trazem um módulo de comunicação SPI ou I2C. Assim só precisas de 2 pinos (o que é muito bom, tendo em conta que o LCD te leva 7).
http://www.ebay.co.uk/itm/New-Blue-IIC-I2C-TWI-2004-20x4-Serial-LCD-Module-Display-Arduino-compatible-/151003806901?pt=UK_BOI_Electrical_Components_Supplies_ET&hash=item2328873cb5

Pedro_Silva:
A ideia de adicionar uma luz externa ao setup é realmente muito bem pensado e interessante!

Pelo menos poupava-te trabalho. Mas adiciona um pouco mais de complicação... Pode ser um upgrade interessante mais à frente talvez, já que não é muito complicado de realizar e não interfere com as sequências.

Pedro_Silva:
Bem acho que está na hora de apresentar algum trabalho,estive a testar com leds e resistências e escrevi um código para ver se consigo aquilo que quero...de notar que nunca programei nenhum Arduino e há 3-4 semanas atrás nem sabia o que isso era,portanto o código que escrevi pode não fazer sentido nenhum,mas aparentemente pelo que observo no funcionamento dos leds,faz aquilo que pretendo.

E se for algo assim?

//
unsigned long time;

#define PASSOS     8

const char pushButton = 13;  //botão de inicio ligado ao pinp 13
const char cameraPin = 10;   //shutter da máquina ligado ao pino 10
const char valvulaPin = 11;  //válvula ligada ao pino 11
const char flashPin = 12;    //flash ligado ao pino 12

//sequências... 
/*
As sequências são definidas por bits. cada unsigned char tem 8 bits. 
Estados                  0     1    2     3    4    5     6     7
bit 0 - Luz exterior  1 -- 0 -- 0 -- 0 -- 0 -- 0 -- 0 -- 1
bit 1 - válvula          0 -- 0 -- 0 -- 1 -- 0 -- 0 -- 0 -- 0
bit 2 - obturador      0 -- 0 -- 0 -- 0 -- 1 -- 1 -- 1 -- 0
bit 3 - flash.            0 -- 0 -- 0 -- 0 -- 0 -- 1 -- 0 -- 0

*/
unsigned char sequencia_pinos[8]; //imagine que a sequência tem 8 estados
unsigned long sequencia_tempo[8]; //tempos entre sequências...

void executa_sequencia(unsigned long start) {
   unsigned char seq_counter = 0; 
   
   for (int i = 0; i < PASSOS; i++) { //percorre as sequencias
      do {
          digitalWrite(luz_exterior, (sequencia_pinos[i] & 0x1));
          digitalWrite(valvula, (sequencia_pinos[i] >> 1) & 0x1);
          digitalWrite(obturador, (sequencia_pinos[i] >> 2) & 0x1);
          digitalWrite(flash, (sequencia_pinos[i] >> 3) & 0x1);
      }while (millis() - start <= sequencia_tempos[i]);  
      start = millis(); //reinicializa temporizacção
   }//end for   
       
}

void setup()
 {
//inicializa sequencia de pinos.
   sequencia_pinos[0] = 0b00000001;
   sequencia_pinos[1] = 0b00000000;
   sequencia_pinos[2] = 0;
   sequencia_pinos[3] = 0b00000010;
   sequencia_pinos[4] = 0b00000100;
   sequencia_pinos[5] = 0b00001100;
   sequencia_pinos[6] = 0b00000100;
   sequencia_pinos[0] = 0b00000001;

//inicializa sequencia de tempos.  
   sequencia_tempos[0] = 1000; //1000 para testar e ver se tudo funciona como deve ser. 
   sequencia_tempos[1] = 1000;
   sequencia_tempos[2] = 1000;
   sequencia_tempos[3] = 1000;
   sequencia_tempos[4] = 1000;
   sequencia_tempos[5] = 1000;
   sequencia_tempos[6] = 1000;
   sequencia_tempos[7] = 1000;
   sequencia_tempos[8] = 1000;


   pinMode(pushButton,INPUT);    //inicia o botão como input
   pinMode(cameraPin,OUTPUT);    //inicia o shutter como output
   pinMode(valvulaPin,OUTPUT);   //inicia a válvula como output
   pinMode(flashPin,OUTPUT);     //inicia o flash como output

     
 }

 
 void loop() { 
    if (digitalRead(pushButton) == 1) { //carregaste no botão
        executa_sequencia(millis());
    }


 }

Nota que isto tem bugs, mas é muito mais flexível pois podes aumentar o numero de saidas e tempos à sequência. Se perceberes como é feita a configuração das saídas com os tempos estás lançado. :slight_smile:
Tenta ver se compila e se faz o que pretendes (coloca uma sequência simples com alterações de luzes em todos os níveis para testar)
Se isto funcionar, depois é uma questão de adicionar o LCD. Isso será o mais complicado. :\ LOL

Pedro_Silva:
Muito bom o trocadilho,LOL

Não estava a fazer um trocadilho... uma das minhas ideias seria mesmo apanhar os meus gatos desprevenidos. LOL

Bem,acho que ando a puxar demais pela cabeça...ainda não consegui perceber como controlar as sequências com oito bits,consigo perceber a ideia de ver isto como sequências e estados que se vão repetindo,mas a sequência de pinos não consigo compreender...

Consegui por o código a compilar,mas não o compreendi e não consigo trabalhar com ele...

//
unsigned long time;

#define PASSOS     8

const char luz_exteriorPin = 9;
const char pushButtonPin = 13;  //botão de inicio ligado ao pinp 13
const char cameraPin = 10;   //shutter da máquina ligado ao pino 10
const char valvulaPin = 11;  //válvula ligada ao pino 11
const char flashPin = 12;    //flash ligado ao pino 12

//sequências... 
/*
As sequências são definidas por bits. cada unsigned char tem 8 bits. 
Estados                  0     1    2     3    4    5     6     7
bit 0 - Luz exterior     1 -- 0 -- 0 -- 0 -- 0 -- 0 -- 0 -- 1
bit 1 - válvula          0 -- 1 -- 0 -- 1 -- 0 -- 0 -- 0 -- 0
bit 2 - obturador        0 -- 1 -- 1 -- 1 -- 1 -- 1 -- 1 -- 0
bit 3 - flash.           0 -- 0 -- 0 -- 0 -- 0 -- 1 -- 0 -- 0

*/
unsigned char sequencia_pinos[8]; //imagine que a sequência tem 8 estados
unsigned long sequencia_tempos[8]; //tempos entre sequências...

void executa_sequencia(unsigned long start) {
   unsigned char seq_counter = 0; 
   
   for (int i = 0; i < PASSOS; i++) { //percorre as sequencias
      do {
          digitalWrite(luz_exteriorPin, (sequencia_pinos[i] & 0x1));
          digitalWrite(valvulaPin, (sequencia_pinos[i] >> 1) & 0x1);
          digitalWrite(cameraPin, (sequencia_pinos[i] >> 2) & 0x1);
          digitalWrite(flashPin, (sequencia_pinos[i] >> 3) & 0x1);
      }while (millis() - start <= sequencia_tempos[i]);  
      start = millis(); //reinicializa temporizacção
   }//end for   
       
}

void setup()
 {
//inicializa sequencia de pinos.
   sequencia_pinos[0] = 0b00000001;
   sequencia_pinos[1] = 0b00000000;
   sequencia_pinos[2] = 0;
   sequencia_pinos[3] = 0b00000010;
   sequencia_pinos[4] = 0b00000100;
   sequencia_pinos[5] = 0b00001100;
   sequencia_pinos[6] = 0b00000100;
   sequencia_pinos[0] = 0b00000001;

//inicializa sequencia de tempo.  
   sequencia_tempos[0] = 1000; //1000 para testar e ver se tudo funciona como deve ser. 
   sequencia_tempos[1] = 1000;
   sequencia_tempos[2] = 1000;
   sequencia_tempos[3] = 1000;
   sequencia_tempos[4] = 1000;
   sequencia_tempos[5] = 1000;
   sequencia_tempos[6] = 1000;
   sequencia_tempos[7] = 1000;
   sequencia_tempos[8] = 1000;


   pinMode(pushButtonPin,INPUT);    //inicia o botão como input
   pinMode(cameraPin,OUTPUT);    //inicia o shutter como output
   pinMode(valvulaPin,OUTPUT);   //inicia a válvula como output
   pinMode(flashPin,OUTPUT);     //inicia o flash como output

     
 }

 
 void loop() { 
    if (digitalRead(pushButtonPin) == 1) { //carregaste no botão
        executa_sequencia(millis());
    }


 }

bubulindo:
Nota que isto tem bugs, mas é muito mais flexível pois podes aumentar o numero de saidas e tempos à sequência. Se perceberes como é feita a configuração das saídas com os tempos estás lançado. :slight_smile:
Tenta ver se compila e se faz o que pretendes (coloca uma sequência simples com alterações de luzes em todos os níveis para testar)
Se isto funcionar, depois é uma questão de adicionar o LCD. Isso será o mais complicado. :\ LOL

Se me puderes abrir os olhos ali na parte do void setup() e na sequência de pinos talvez compreenda...
Adicionar o LCD é ainda mais complicado ainda?
Então acho que é melhor ficar por aqui,LOL

Não fiques assim... o teu código também funciona, mas não é muito flexível por causa dos delays.

Este é um pouco mais complexo, mas após compreenderes o objectivo torna-se simples.

Reparei que a parte da sequência estava desalinhada, se meteres alinhado talvez consigas ver melhor.
Os bits são vistos da direita para a esquerda, ou seja, o bit mais à direita é o zero, o seguinte à o um, etc... Esses bits indicam o estado das luzes ou válvula em cada momento. Como podes ver, no primeiro estado a lampada externa (que ainda não tens no teu sistema) está ligada para tu preparares tudo. Depois o estado 1 diz-te que a lâmpada está apagada e a válvula e obturador estão abertos. Depois apenas o obturador, depois o obturador e a válvula.

No setup tens a definicão da sequencia. Onde eu escrevi a explicacão da sequencia, o numero do estado é o indice do vector sequencia_pinos e o valor que eu coloquei é visto por de cima para baixo. Ou seja:

estado zero - 0b00000001
estado um - 0b00000110
estado dois - 0b00000100

... estás a ver a mecânica?

O vector estado_tempos indica o tempo que demora a passar de estado para estado.
Hoje talvez tenha algum tempo para ver isto por casa com uns leds e se a sequencia funciona (ontem usei um bocado de código semelhante para simular um encoder, por isso deve dar).

bubulindo:
Não fiques assim... o teu código também funciona, mas não é muito flexível por causa dos delays.

Este é um pouco mais complexo, mas após compreenderes o objectivo torna-se simples.

Reparei que a parte da sequência estava desalinhada, se meteres alinhado talvez consigas ver melhor.
Os bits são vistos da direita para a esquerda, ou seja, o bit mais à direita é o zero, o seguinte à o um, etc... Esses bits indicam o estado das luzes ou válvula em cada momento. Como podes ver, no primeiro estado a lampada externa (que ainda não tens no teu sistema) está ligada para tu preparares tudo. Depois o estado 1 diz-te que a lâmpada está apagada e a válvula e obturador estão abertos. Depois apenas o obturador, depois o obturador e a válvula.

No setup tens a definicão da sequencia. Onde eu escrevi a explicacão da sequencia, o numero do estado é o indice do vector sequencia_pinos e o valor que eu coloquei é visto por de cima para baixo. Ou seja:

estado zero - 0b00000001
estado um - 0b00000110
estado dois - 0b00000100

... estás a ver a mecânica?

O vector estado_tempos indica o tempo que demora a passar de estado para estado.
Hoje talvez tenha algum tempo para ver isto por casa com uns leds e se a sequencia funciona (ontem usei um bocado de código semelhante para simular um encoder, por isso deve dar).

AHH,da direita para a esquerda :slight_smile: era isso que me estava a fazer confusão pois estava a tentar ler ao contrário,assim já estou a ver melhor,mas aquele primeiro "0" da esquerda e o "b",o que significam?

Vou estar uns dias sem internet e em principio só posso continuar isto no fim de semana,mas volto aqui logo que possa :wink:

o 0b é para indicar ao arduino que o numero que está à frente é para ser pensado como um numero binário e não um inteiro. Se nõa indicares isso, o arduino pensa que aquilo é um numero inteiro na ordem dos milhões. :wink:

bubulindo:
... depois é uma questão de adicionar o LCD. Isso será o mais complicado. :\ LOL

Olá :slight_smile:

Estive a ver onde conseguia chegar na configuração e nos menus do lcd,mas não me safo :astonished: é mesmo complicado para mim,podes abrir um pouco o caminho?Sozinho está visto que não vou lá!

Para começar tens de ter teclas... tendo isso, podes definir o que é que elas fazem.

Por exemplo, ter um cursor para andar para cima e outra para baixo, ou só uma para andar em frente e dar a volta. Uma tecla para cancelar e uma tecla para confirmar será o minimo.

Depois tens de definir a árvore dos menus. Depois torna-se mais fácil de codificar pois dá para ver as interacções que são necessárias para mexer nos menus. :slight_smile:

Começa por aí e depois eu coloco aqui um exemplo (genérico) para implementar um sistema de menus.

Nota também que os menus podem ocupar imenso espaço de memória se pretenderes colocar imensas strings com descrições do menu. Por isso acho melhor fazer algo bem simples no menu, ou então usar indices em vez de strings de texto.

Pensa conceptualmente.

Faz um esquema do que pretendes e de como as teclas que tens disponíveis te vão levar lá. Depois disso estar pronto, o resto é relativamente fácil. Pensa nisso primeiro... pensa também que parâmetros queres ajustar... nota que a sequência que tens tem imensos parâmetros para ajustar. Talvez queiras simplificar isso com o LCD e só tenhas a possibilidade de ajustar uns poucos. Tudo isso é importante definir antes de andar para a frente.

Infelizmente com 3 litros de cerveja no bucho não consigo ser muita ajuda de momento. Amanhã tiro um tempinho para deixar aqui um exemplo ou um esqueleto para veres a mecânica.

Eu bem tenho estudado,mas isto é muito complicado para alguém como eu que não tem bases nenhumas nisto...

Estive a tentar perceber quantos menus preciso e parece.me que bastam 3:

MENU ENTRADA
linha 1 -------------Gota_1
linha 2--------------Gota_2

MENU_1_Gota_1
linha 1--------------Tamanho(1º tempo da minha sequência_tempos)
linha 2--------------Tempo_Atraso(2º tempo da minha sequência_tempos)

MENU_2_Gota_2
linha 1--------------Tamanho(3º tempo da minha sequência_tempos)
linha 2--------------Tempo_Atraso(4º tempo da minha sequência_tempos)

Os outros tempos serão fixos depois dos ajustes iniciais...
Mas estou com extrema dificuldade em criar os menus e a navegação através das teclas,por mais que me esforce,parece-me uma tarefa impossível para mim.

Penso que a questão da definição das teclas consigo fazer,mas isso é só ir à biblioteca da minha Shield e copiar,a biblioteca está aqui: 16 X 2 LCD Keypad Shield for Arduino - LinkSprite Playgound

Eu não estou a conseguir passar disto:

/*--------------------------------------------------------------------------------------
  Includes
--------------------------------------------------------------------------------------*/
#include <LiquidCrystal.h>   // include LCD library
/*--------------------------------------------------------------------------------------
  Defines
--------------------------------------------------------------------------------------*/

// Pins in use
#define BUTTON_ADC_PIN           A0  // A0 is the button ADC input
#define LCD_BACKLIGHT_PIN         10  // D10 controls LCD backlight
// ADC readings expected for the 5 buttons on the ADC input
#define RIGHT_10BIT_ADC           0  // right
#define UP_10BIT_ADC            145  // up
#define DOWN_10BIT_ADC          329  // down
#define LEFT_10BIT_ADC          505  // left
#define SELECT_10BIT_ADC        741  // right
#define BUTTONHYSTERESIS         10  // hysteresis for valid button sensing window
//return values for ReadButtons()

#define BUTTON_NONE               0  // 
#define BUTTON_RIGHT              1  // 
#define BUTTON_UP                 2  // 
#define BUTTON_DOWN               3  // 
#define BUTTON_LEFT               4  // 
#define BUTTON_SELECT             5  // 
//some example macros with friendly labels for LCD backlight/pin control, tested and can be swapped into the example code as you like
#define LCD_BACKLIGHT_OFF()     digitalWrite( LCD_BACKLIGHT_PIN, LOW )
#define LCD_BACKLIGHT_ON()      digitalWrite( LCD_BACKLIGHT_PIN, HIGH )
#define LCD_BACKLIGHT(state)    { if( state ){digitalWrite( LCD_BACKLIGHT_PIN, HIGH );}else{digitalWrite( LCD_BACKLIGHT_PIN, LOW );} }
//Numero de Menus
#define Numero_de_Menus    3
/*--------------------------------------------------------------------------------------
  Variables
--------------------------------------------------------------------------------------*/
byte buttonJustPressed  = false;         //this will be true after a ReadButtons() call if triggered
byte buttonJustReleased = false;         //this will be true after a ReadButtons() call if triggered
byte buttonWas          = BUTTON_NONE;   //used by ReadButtons() for detection of button events
/*--------------------------------------------------------------------------------------
  Init the LCD library with the LCD pins to be used
--------------------------------------------------------------------------------------*/
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );   //Pins for the freetronics 16x2 LCD shield. LCD: ( RS, E, LCD-D4, LCD-D5, LCD-D6, LCD-D7 )

//
unsigned long time;

#define PASSOS     8


const char pushButtonPin = 29;  //botão de inicio ligado ao pinp 13
const char cameraPin = 25;   //shutter da máquina ligado ao pino 10
const char valvulaPin = 27;  //válvula ligada ao pino 11
const char flashPin = 23;    //flash ligado ao pino 12

//sequências... 
/*
As sequências são definidas por bits. cada unsigned char tem 8 bits. 
Estados                     0    1    2    3    4    5    6    7

bit 0 - valvulaPin          1 -- 0 -- 1 -- 0 -- 0 -- 0 -- 0 -- 0
bit 1 - cameraPin           0 -- 0 -- 0 -- 0 -- 1 -- 1 -- 1 -- 0
bit 2 - flashPin            0 -- 0 -- 0 -- 0 -- 0 -- 1 -- 0 -- 0

*/
unsigned char sequencia_pinos[7]; //imagine que a sequência tem 8 estados
unsigned long sequencia_tempos[7]; //tempos entre sequências...

void executa_sequencia(unsigned long start) {
   unsigned char seq_counter = 0; 
   
   for (int i = 0; i < PASSOS; i++) { //percorre as sequencias
      do {
          digitalWrite(valvulaPin, (sequencia_pinos[i] & 0x1));
          digitalWrite(cameraPin, (sequencia_pinos[i] >> 1) & 0x1);
          digitalWrite(flashPin, (sequencia_pinos[i] >> 2) & 0x1);
          
      }while (millis() - start <= sequencia_tempos[i]);  
      start = millis(); //reinicializa temporizacção
   }//end for   
       
}

void setup()
{


   //button adc input
   pinMode( BUTTON_ADC_PIN, INPUT );         //ensure A0 is an input
   digitalWrite( BUTTON_ADC_PIN, LOW );      //ensure pullup is off on A0
   //lcd backlight control
   digitalWrite( LCD_BACKLIGHT_PIN, HIGH );  //backlight control pin D3 is high (on)
   pinMode( LCD_BACKLIGHT_PIN, OUTPUT );     //D3 is an output
   //set up the LCD number of columns and rows: 
   lcd.begin( 16, 2 );
   //Print some initial text to the LCD.
   lcd.setCursor( 0, 0 );   //top left
   //          1234567890123456
   lcd.print( "Ola" );
   //
   lcd.setCursor( 0, 1 );   //bottom left
   //          1234567890123456
   lcd.print( "Pedro" );

 
//inicializa sequencia de pinos.
   sequencia_pinos[0] = 0b0000001;
   sequencia_pinos[1] = 0b0000000;
   sequencia_pinos[2] = 0b0000001;
   sequencia_pinos[3] = 0b0000000;
   sequencia_pinos[4] = 0b0000010;
   sequencia_pinos[5] = 0b0000110;
   sequencia_pinos[6] = 0b0000010;
   sequencia_pinos[7] = 0b0000000;

//inicializa sequencia de tempo.  
   sequencia_tempos[0] = 200; //tamanho gota 1
   sequencia_tempos[1] = 1000; //tempo que demora gota 1 cair
   sequencia_tempos[2] = 400; //tamanho gota 2
   sequencia_tempos[3] = 700; //tempo que demora gota 2 colidir com gota 1
   sequencia_tempos[4] = 200; //atraso entre abertura obturador e disparo do flash
   sequencia_tempos[5] = 10; //tempo de disparo do flash
   sequencia_tempos[6] = 100; //atraso fecho obturador depois do flash disparar

   pinMode(pushButtonPin,INPUT);    //inicia o botão como input
   pinMode(cameraPin,OUTPUT);    //inicia o shutter como output
   pinMode(valvulaPin,OUTPUT);   //inicia a válvula como output
   pinMode(flashPin,OUTPUT);     //inicia o flash como output

     
 }

 
 void loop() { 
    if (digitalRead(pushButtonPin) == 1) { //carregaste no botão
        executa_sequencia(millis());
    }


 }

Preciso mesmo de um grande empurrão,se puderes ajudar,agradeço!

Ok... vamos dividir para conquistar.

Primeiro esquece a parte das gotas. Sabemos que temos 4 variáveis para ajustar. Não percebi o que queres dizer por menu de entrada. Se vires um LCD de 16 caracteres, não consegues meter lá muita informação.

Aqui fica um excerto da mecânica.
Infelizmente não é muito complexo e certamente que tem bugs, mas mostra como se faz, basicamente vais andando para cima e para baixo consoante as teclas que usaste.
Vais usar um LCD shield? Uma coisa boa do LCD shield é que usa o analogRead() para detectar o botão usado e isso faz com que não tenhas problemas de bounce.

#define NUMERO_MENUS 3

#define MENU_HOME 0
#define MENU_GOTA1 1
#define MENU_GOTA2 2

unsigned char menu_move = 0;
unsigned char menu_enter = 0;
unsigned char menu_exit = 0;

unsigned char estado_menu = 0;
unsigned char sub_menu = 0;
unsigned int temp = 0;
unsigned int parametro1 = 0;
unsigned int parametro2 = 0;

unsigned int parametros[3]; //estes ser~o os parametros que usas no teu programa das gotas

switch(estado_menu) {
case MENU_HOME: {
lcd.print("Gota 1");
lcd.print("Gota 2");
if (menu_move == TRUE) {
temp = (temp+1)%3;
}
lcd.print("menu");
lcd.print(temp);
if (menu_enter == TRUE) {
estado_menu = temp;
}
break;
case MENU_GOTA1: { //agora ficamos aqui dentro...
switch(sub_menu) {
case 0: {
lcd.print("move cursor para escolher parametro");
if (menu_move == TRUE) {
temp = (temp+1)%3;
}
lcd.print("menu");
lcd.print(temp);
if (menu_enter == TRUE) {
sub_menu = temp;
}
break;
}
case 1: {
lcd.clear();
lcd.print("ajuste parametro 1");
if (menu_move == TRUE)
parametro1++;
lcd.setCursor(0,1);
lcd.print(parametro1);
if (menu_enter == TRUE) {
parametros[0] = parametro1;
}
if (menu_exit == TRUE) {
sub_menu = 0;
}
break;
}
case 2: {
lcd.clear();
lcd.print("ajuste parametro 1");
if (menu_move == TRUE)
parametro2++;
lcd.setCursor(0,1);
lcd.print(parametro2);
if (menu_enter == TRUE) {
parametros[1] = parametro2;
}
if (menu_exit == TRUE) {
sub_menu = 0;
}
break;
}//end case 2

}//end switch sub_menu
}//end switch

Como podes ver é um pouco complicado, mesmo para um menu simples como este.

Com um interface série seria um pouco mais simples de programar, mas terias de ter o computador ao teu lado para configurar o bicho.

Infelizmente não tenho um lcd para fazer um programa completamente funcional e testado para veres. :frowning:

Isto é uma autêntica montanha para mim :astonished: uma coisa que parece tão simples,afinal é tão complexa :astonished:

No enxerto que meteste ainda falta configurar o menu da gota 2,certo?

Meti o código,mas diz-me que "TRUE" não está declarado...

TRUE Pode ser qualquer coisa.. normalmente é 1. Podes também trocar por HIGH.

Viva,

Acho que o problema está em não usares o lcd.clear() sempre que queres colocar dados novos no LCD ou fazer mudança de menú e também não fazeres uso da função setCursor() para posicionar o cursor.

void trata_lcd(){
  
  
  switch(estado_menu) {
  case MENU_HOME: { 
    lcd.print("Gota 1");
    lcd.setCursor(0,1);   <----------------ADICIONADO
    lcd.print("Gota 2");
    if (BUTTON_UP == HIGH) {
      temp = (temp+1)%3;
      }
      lcd.clear(); <-----------------------ADICIONADO
      lcd.print("menu");
      lcd.print(temp);
      if (BUTTON_RIGHT == HIGH) {
        estado_menu = temp;
      }
      break;