Voltage drop issue - camera intervalometer

The code below I wrote to provide an endless automated long exposure sequence for astrophotography - the current exposure values are test only.

The circuit is very basic. Digital pin 5 and 6 are connected to separate inputs of an optocoupler via 1k ohm resistors in series. Pins are set HIGH or LOW to operate the camera mirror/focus and shutter respectively.

The problem that I cannot answer, is a voltage drops across the resistor connected to DP5, whereas there is no voltage drop across the resistor connected to DP6. I haven't yet connected the camera - in one sense the circuit is not complete.

The thing that I don't understand is that the voltage to both resistors is the same (+5v), and the voltage drop to +1.5v is across one resistor only.

Could this be something simple such as a poor GND connection?

Many thanks.

Code:

/* An intervalometer script for Canon DSLR 1000D.
Change int mirror and int shutter variables to adjust exposure times.
*/

int shutterval; // Read this value
int mirrorval; // Read this value

int mirror = 3000; // Mirror lock up/focus time
int shutter = 6000; // Shutter release time
int wait = 3000; // Switch off opportunity

int mirrorpin = 5; // Mirror lock up/focus
int shutterpin = 6; // Shutter release

void setup() {

pinMode(mirrorpin, OUTPUT);
pinMode(shutterpin, OUTPUT);

}

void loop() {

mirrorval = digitalRead(mirrorpin);
shutterval = digitalRead(shutterpin);
if (mirrorpin != HIGH && shutterpin != HIGH);

{

digitalWrite(mirrorpin, HIGH);
digitalWrite(shutterpin, HIGH);
delay(wait);

}

mirrorval = digitalRead(mirrorpin);
shutterval = digitalRead(shutterpin);
if (shutterval == HIGH && mirrorval == HIGH); // make sure mirror and shutter are closed

{

digitalWrite(mirrorpin, LOW); // Mirror lock up
delay(mirror); // Remains open until shutter close
}
{
mirrorval = digitalRead(mirrorpin);
shutterval = digitalRead(shutterpin);
if (mirrorval == LOW && shutterval == HIGH); // make sure mirror is open

digitalWrite(shutterpin, LOW); // Shutter release
delay(shutter); // Exposure time - then start again

}
}

No voltage drop means no current, meaning current has nowhere to go. I'd check to see if the optocoupler cathode is solidly connected to GND.

Any chance you got the pinout of the optocoupler wrong and you're actually connecting DP6 to the cathode?

--
Need a custom shield? Let us design and build one for you.

why you are READing the values of OUTput pins?... I don't know if it is even defined what happens if you read an output pin? I certainly wouldn't trust writing code that depends on that.

Uh, this is a very clearly defined behavior. (And a very common practice.) Reading an OUTPUT pin will give the PORT's register value, returning the pin's current state (high or low). The original poster is checking to see what state the pin was in before performing an action.

It is reason why this works for toggling:

  int ledPin = 13;
  pinMod(ledPin, OUTPUT);
  while(1) {
     digitalWrite(ledPin, !(digitalRead(ledPin)));
     delay(1000);
   }

agreed, you should be in control of your program, if not you need to figure out why

IMHO, that is terrible programing practice.

I don't know... As CMiYC said, this is common practice among most programmers (which I know) outside the Arduino world. It is quite elegant code in assembly language, and a memory element is a memory element. You are indeed forced to work so with RAM less controllers, and the output register - is just another register.

I'll take all that on board. I here what you're saying re-programming.

No voltage drop means no current, meaning current has nowhere to go. I'd check to see if the optocoupler cathode is solidly connected to GND.

Any chance you got the pinout of the optocoupler wrong and you're actually connecting DP6 to the cathode?

I agree, there's a problem in the circuit. I'll check the pinout on the optocoupler again.

IMHO, that is terrible programing practice.

You are welcome to your opinion, but you are being obtuse on this point. There are perfectly valid reasons to write code like this and there are other examples. Could you state that a digitalWrite() to an INPUT pin is a "terrible programming practice?" No you couldn't, because it is the only way to enable or disable the internal Pull-Ups.

Here's another example, setting an OUTPUT to be Tri-Stated. How do you do that? You change an OUTPUT pin to an INPUT pin. Could you state that is a "terrible programming practice?"

The very reason micro-controllers have a register for the I/O ports is so that you can do actions like "read an output." Otherwise you would be forced to use RAM to keep track of the state of your output pins. This is probably a worse programming practice: using extra resources to do a job already provided by the hardware!

Can it lead to confusion when reading code? Sure. Is it a "terrible" practice, no! The micro-controller environment requires some creativity to deal with the limited resources available to you. In a case such as this, a GOOD programming practice would be to comment and say "checking to see what state the OUTPUT pin was left in."

I see absolutely no reason anyone would want to read an output pin, unless the pin was some sort of shared input/output function (which this does not appear to be)

You say "absolutely no reason" and then "unless." You can't be absolute with exceptions.

The objection is that we have an OUTPUT pin. It is ONLY and ALWAYS an OUTPUT pin. It should be under the code's constant and supreme control.

THIS is the exact point you are being obtuse on. You want to shout "BAD PROGRAMMING!" so loud, you are not looking at the bigger picture. In fact, you are suggesting a potentially bad programming practice at the same time.

You SHOULD use a proper variable to track each parameter of what the code is dealing with.

THERE ALREADY IS ONE. Every PORT has an I/O Register! When you issue a digitalRead(), the PINx register is what is read. In the case of INPUT pins, this value will depend on the last value clocked into the register from the physical pin. In the case of OUTPUT pins, the value is whatever you last wrote to it.

What if it is accidentally or temporarily shorted to ground, or to +5V? (As from plugging in a connector, etc.)

Since you are not reading the STATE of the PIN, but the register which determines it, it does not matter what the Pin is connected to.

This behavior is no different than if you have a variable tracking the state of the pin. Except that you are using a wasted variable to track something already built in the Micro-controller's hardware. Your opinion is that this is a Bad programming practice. Sorry, but I and most of the RealWorld(TM) will disagree with you.

From ATmel's Own Documentation:
13.2.4 Reading the Pin Value
"Independent of the setting of Data Direction bit DDxn, the port pin can be read through the PINxn Register bit.."

I point this out because the documentation clearly refers to the PINx Register, which is also illustrated below.

From wiring_digital.c:
int digitalRead(uint8_t pin)
{
      uint8_t timer = digitalPinToTimer(pin);
      uint8_t bit = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin);

      if (port == NOT_A_PIN) return LOW;

      // If the pin that support PWM output, we need to turn it off
      // before getting a digital reading.
      if (timer != NOT_ON_TIMER) turnOffPWM(timer);

      if (*portInputRegister(port) & bit) return HIGH;  // CMIYC is referring to this line below.
      return LOW;
}

Now before you say "But there! See! It says 'portInputRegister'" you have to go and look to see what that is defined as, which is:

in pins.arduino.h:
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )

in pins_arduino.c:
const uint16_t PROGMEM port_to_input_PGM[] = {
      NOT_A_PIN,
      &PINA,
      &PINB,
      &PINC,
      &PIND,
      &PINE,
      &PINF,
      &PING,
      &PINH,
      NOT_A_PIN,
      &PINJ,
      &PINK,
      &PINL,
};

The PINx register keeps track of the value of the PIN, regardless of its state. When you issue a digitalRead(), the register PINx is read and its value returned. Perhaps the Arduino language would benefit from pinRegisterRead() or something similar.

However, as I pointed out in my previous examples the Arduino language does not always have the most logical syntax for all aspects of the hardware's features. (e.g. enabling the Pull-Up resistors.)

A very good read. Heated but informative.

That's my second attempt at programming. I tried both methods prior to starting this thread and they both worked.

I'm not sure who is correct. Perhaps both in the context of the application - it's not critical - although the timing of the mirror and shutter is important for photographic reasons, there is no mechanical linkage that could lead to breakage.

Suggestions for improvement welcome.

We seem to have strayed from the original question which to be looks 100% like a hardware problem. Basically what in two seemingly identical setups is different to make one work and the other not.
Schematics need to be posted.

OK. I've found it. 100% hardware problem it is. The optocoupler pinout is slightly different to that of the original circuit design - my mistake.

One cathode 'is' connected to DP6, it should be to ground.

Not wishing to start a flame war, should I change the pins to INPUT in setup, or just leave it as it is.

just leave it as it is. :wink:

thanks for that :slight_smile:

Not wishing to start a flame war, should I change the pins to INPUT in setup, or just leave it as it is.

I apologize for getting carried away. The messages should have gone private.

Set the pin for the function you need them to be. In this case (from what I can tell) you need them function as an OUTPUT. It looks like you are trying to control your optocouplers.

That's correct. A direct connection between the arduino and camera probably wouldn't hurt - just a matter of sending the camera mirror and shutter activation circuits to ground.