Using DigiSpark To Implement A Delay Circuit

Have questions about the equipment used for macro- or micro- photography? Post those questions in this forum.

Moderators: rjlittlefield, ChrisR, Chris S., Pau

mjkzz
Posts: 1681
Joined: Wed Jul 01, 2015 3:38 pm
Location: California/Shenzhen
Contact:

Using DigiSpark To Implement A Delay Circuit

Post by mjkzz »

Sometimes, it is necessary to trigger flash or turn on the light in the middle of exposure to avoid vibration caused by shutter opening and closing such as front and rear curtain trigger (or some might call it 1st and 2nd curtain trigger). So, a delay circuit is necessary to do this.

While others use classical analog circuit (Mike's), I decided to do it with digital approach. Trying to maintain DIY'ability, it seems that DigiSpark board from fellow Kickstarter project (which I forgot at first) seems to be good choice. DigiSpark is cheap on eBay, but I am not sure if they are licensed from DigiStump and these cheap boards seem to have some flaws (or even the original has them, too)

Nonetheless, it turns out the DigiSpark is the right choice and then some -- I can even shove a OLED display in. Construction of circuit is described in the code (see below), it is rather simple with some exceptions -- pin 1 of the board seems to be tied to the on-board LED, so it must be pulled up with a 10K resistor (1K in my photo as I could not find one). Another exception is that the cheap DigiSpark board is probably a rip-off one, its pin 5, the reset pin is still ENABLED for reset. I do not have genuine DigiSpark board (they stopped selling till May) to test, so if you turn the POT and change voltage to lower than 2.5V, the board resets. Oh well, that is life :D

Output (in the picture) is now an LED instead of a transistor to trigger flash (or other lights), but it should be easy to change.

One key idea is to use the POT to change the voltage on an ADC pin, in this example, the P5 (analog 0). By turning the POT, you are changing the voltage and the DigiSpark can read it and convert that to change amount of delay.


Image

Code:

Code: Select all

#include <DigisparkOLED.h>    // DigiSpark OLED driver
#include <Wire.h>

// OLED I2C Slave address, this is important as different OLED might have different address
#define SSD1306_SA  0x78      

// P0 is used for I2C SDA -- OLED Display
// P2 is used for I2C SCK -- OLED Display
// P1 is used for INPUT from camera or stack controller
// P5 is used as analog pin &#40;analog 0&#41;
// P4 is used as output to trigger flash or light


enum enumMode
&#123;
  mode_idle,
  mode_down,
  mode_wait,
  mode_fire,
  
  mode_last,
&#125;;


#define PIN_INPUT         1       // we use P1 as input signal from either camera or stack controller
#define PIN_OUTPUT        4       // use P4 as output to trigger flash/light
#define PIN_ANALOG        5       // Analog 0 is P5
#define PIN_ANALOG_NUM    0       // Analog 0 is P5

#define MAX_FLASH_DUR     200     // this controls how long the flash/lite is ON in milliseconds
// this is used to increase range.
#define MULTIPLIER        1
// this defines how often the POT is read
#define MAX_READ_TICK     30000

byte gv_ucMode  = mode_idle;
long gv_tkRead  = MAX_READ_TICK;

long gv_tkFire  = MAX_FLASH_DUR;
long gv_slTick  = 0;
long gv_tnWait  = 0;
long gv_tkWait  = 0;

// here to implement a digital filter on the ADC
// as ADC is very, very noisy.
#define NUM_FILTER    16

long gv_svRead = 0;
long gv_slRead = 0;
long gv_arRead&#91;NUM_FILTER&#93;;
byte gv_ixRead = 0;


// this is a routine that takes a long value
// and fill it up to a buffer, right aligned

#define BUFFER_SIZE 6
byte gv_arBuffer&#91;BUFFER_SIZE&#93;;

void fillBuffer&#40;long val&#41;
&#123;
  for&#40;byte i=0; i<BUFFER_SIZE-1; i++&#41;
  &#123;
    gv_arBuffer&#91;i&#93; = ' ';
  &#125;

  byte  ucVal;
  byte  index = BUFFER_SIZE-2;
  
  while&#40;index&#41;
  &#123;
    gv_arBuffer&#91;index&#93; = val - &#40;val / 10&#41; * 10 + '0';
    if &#40;index > 0&#41;
    &#123;
      index--;
    &#125;
    val = val / 10;   
    if &#40;val == 0&#41;
    &#123;
      break;
    &#125;
  &#125;

  // finally, terminate the string with NULL
  gv_arBuffer&#91;BUFFER_SIZE-1&#93; = 0;
&#125;

void setup&#40;&#41; 
&#123;  
  // for analog read, no need to configure it.
  
  // but for digital read, we need to
  pinMode&#40;PIN_INPUT, INPUT&#41;;        
  digitalWrite&#40;PIN_INPUT, HIGH&#41;;      // set pullup resistor on INPUT by writing HIGH to it.

  pinMode&#40;PIN_OUTPUT, OUTPUT&#41;;        // we use P4 for output to trigger flash
  digitalWrite&#40;PIN_OUTPUT, LOW&#41;;      // set initial state

  pinMode&#40;PIN_ANALOG, INPUT&#41;;         // make analog pin INPUT pin
  
  oled.begin&#40;&#41;;
  
  // clear screen
  oled.clear&#40;&#41;;                     //all black     
  // set OLED fonts
  // oled.setFont&#40;FONT6X8&#41;;         // smaller font
  oled.setFont&#40;FONT8X16&#41;;           // large font

  oled.setCursor&#40;12, 6&#41;;
  oled.print&#40;F&#40;"www.mjkzz.com"&#41;&#41;;
&#125;

void loop&#40;&#41; 
&#123;    
  switch&#40;gv_ucMode&#41;
  &#123;
    case mode_idle&#58;
      // sense INPUT
      if &#40;digitalRead&#40;PIN_INPUT&#41; == LOW&#41;
      &#123;
        gv_tkWait = gv_tnWait;

        gv_ucMode = mode_wait;          // down edge triggered
        // gv_ucMode = mode_down;       // up edge triggered
      &#125;
      else
      &#123;
        if &#40;gv_tkRead == 0&#41;
        &#123;
          gv_arRead&#91;gv_ixRead&#93; = analogRead&#40;PIN_ANALOG_NUM&#41;;
          gv_ixRead++;
          if &#40;gv_ixRead > NUM_FILTER-1&#41;
          &#123;
            gv_ixRead = 0;         
          &#125;

          gv_slRead = 0;
          for&#40;byte i=0; i<NUM_FILTER; i++&#41;
          &#123;
            gv_slRead += gv_arRead&#91;i&#93;;
          &#125;
          gv_slRead /=  NUM_FILTER;

          if &#40;gv_slRead != gv_svRead&#41;
          &#123;
            // new reading
            gv_svRead = gv_slRead;
            gv_tnWait = gv_slRead * MULTIPLIER;            
            
            oled.setCursor&#40;5, 2&#41;;
            oled.print&#40;F&#40;"Delay &#58; "&#41;&#41;;
            fillBuffer&#40;gv_tnWait&#41;;
            oled.print&#40;&#40;char *&#41; gv_arBuffer&#41;;
            oled.println&#40;F&#40;"ms"&#41;&#41;;
          &#125;
          gv_tkRead = MAX_READ_TICK;
        &#125;
        else
        &#123;
          gv_tkRead--;
        &#125;
      &#125;
      break;
    case mode_down&#58;
      if &#40;digitalRead&#40;PIN_INPUT&#41; == HIGH&#41;
      &#123;
        gv_ucMode = mode_wait;        
      &#125;
      break;
    case mode_wait&#58;
      if &#40;gv_tkWait&#41;
      &#123;
        gv_tkWait--;
        delay&#40;1&#41;;       // every tick is 1ms
      &#125;
      else
      &#123;        
        gv_ucMode = mode_fire;
        gv_tkFire = MAX_FLASH_DUR;
        digitalWrite&#40;PIN_OUTPUT, HIGH&#41;;    
      &#125;
      break;
    case mode_fire&#58;
      if &#40;gv_tkFire&#41;
      &#123;
        digitalWrite&#40;PIN_OUTPUT, HIGH&#41;;
        gv_tkFire--;
        delay&#40;1&#41;;       // every tick is 1ms
      &#125;
      else
      &#123;
        // finished job, set flash off
        digitalWrite&#40;PIN_OUTPUT, LOW&#41;;
        gv_ucMode = mode_idle;
      &#125;
      break;
    default&#58;
      gv_ucMode = mode_idle;
      break;      
  &#125;
&#125;
[Admin edit, RJL: add code tags]

rjlittlefield
Site Admin
Posts: 23561
Joined: Tue Aug 01, 2006 8:34 am
Location: Richland, Washington State, USA
Contact:

Post by rjlittlefield »

Great info, thanks for posting.

I took the liberty of adding some

Code: Select all

 block tags to your post, to improve the readability.

--Rik

mjkzz
Posts: 1681
Joined: Wed Jul 01, 2015 3:38 pm
Location: California/Shenzhen
Contact:

Post by mjkzz »

oh, wow, thanks Rik. I see there is a code tag here.

Saul
Posts: 1781
Joined: Mon Jan 31, 2011 11:59 am
Location: Naperville, IL USA
Contact:

Re: Using DigiSpark To Implement A Delay Circuit

Post by Saul »

mjkzz wrote:... Output (in the picture) is now an LED instead of a transistor to trigger flash (or other lights), but it should be easy to change.

One key idea is to use the POT to change the voltage on an ADC pin, in this example, the P5 (analog 0). By turning the POT, you are changing the voltage and the DigiSpark can read it and convert that to change amount of delay. ...
Hi Peter,
Very nice & compact design.
"... to trigger flash (or other lights)" - can be output signal length adjusted in order to control continuous light in this configuration ?
Saul
μ-stuff

ChrisR
Site Admin
Posts: 8668
Joined: Sat Mar 14, 2009 3:58 am
Location: Near London, UK

Post by ChrisR »

Peter, did you have a reason to not use the trailing edge of the pulse which triggers the shutter? Then you just set the timing in the set-up (in Stackshot operation at least).
Chris R

mjkzz
Posts: 1681
Joined: Wed Jul 01, 2015 3:38 pm
Location: California/Shenzhen
Contact:

Post by mjkzz »

Saul: yes, there is a define, MAX_FLASH_DUR, now it is set to 200ms, you can change it. But if you want dynamic ones, you can add another POT for it.

ChrisR: not sure what you mean by trailing edge, if you mean the edge going from low to high (normally, camera or other devices pulls input low and then high when released), then yes there is a reason -- if camera is in bulb mode or long exposure mode, you can not fire a flash in the middle as the camera will continue hold the signal low till it release the shutter.

For other purposes, you can comment out the "down edge triggered" and un-comment the "up edge triggered" to make the circuit respond to the edge when signal going from low to high.

Essentially, the program is a state machine.
Last edited by mjkzz on Wed Feb 28, 2018 8:31 pm, edited 2 times in total.

mjkzz
Posts: 1681
Joined: Wed Jul 01, 2015 3:38 pm
Location: California/Shenzhen
Contact:

Post by mjkzz »

To be honest, this is my first time using and programming the board, it took me four hours to finish it, most of the time was to figure out some peculiarity of the board, a lot of googling :-)

For those interested and want to avoid some time consuming part that I encountered, here is my blog on how to get started.. Good luck.

Post Reply Previous topicNext topic