Go Down

Topic: EM shutter almost working. Still a few things needed... (Read 2021 times) previous topic - next topic

vaj4088

I am sorry that changing the pins did not work out for you.

With the requirements that you have posted and the bit that I have had to glean from the code that you posted and with few decisions to make, this code should practically write itself.

Unfortunately, I have some other priorities that I must attend to, so it may be about two days before I get back to this. I hope to try at that time.


vaj4088

Questions:  The only input is called "IN" and its mode is set to INPUT rather than the more common INPUT_PULLUP.  What is connected to this pin?  Can you provide a schematic?



 

Quoll

At the moment I am just running this on a breadboard with LEDs to indicate what each output is doing. I have a schematic in mind but can't test it until the code is doing what it is supposed to do...
Nathan Litjens

vaj4088

LEDs are a good way to check things out, but you still have not explained what is connected to pin 4.  Even if it is just a wire or a switch for the test, it needs a pullup or pulldown resistor.

What is currently connected?
What will be connected?
Do you want the shutter triggered when pin 4 goes HIGH or when pin 4 goes LOW?


vaj4088

I have posted some code below which may work for you.

Caveat:
The code compiles for an Uno using the Arduino IDE version 1.8.1.  That does not mean that it will compile for an ATTiny, and that does not mean that it will execute correctly.

I salute you for working with an ATTiny.  I have never tried to compile for an ATTiny.
An ATTiny does not have a Serial port, so I should not have mentioned pins 0 and 1.  Sorry.

I do not have your hardware, so I have not tested this code. 
Furthermore, some of my questions were never answered.
Furthermore, the requirements had some ambiguities in them.
Furthermore, the requirements had some contradictions in them.
Furthermore, I may have made mistakes.
This code is a starting point.  You may have to adjust it for your purposes, but it may show you how to get from requirements to code.

There are some "else" statements that are empty (except for a comment).  They could be omitted but I kept them to make it more clear what is happening.

A "switch/case" statement is just an advanced way of doing a series of "if/else if" statements.

Some of the variables and some of the states should have better names based on what the system does rather than how the system does something, but I did not have more information.

There are some things that I could have done to save space or save time, but I did not want to get too tricky... yet.

Is this code more complex than the original interrupt-based register-based code?  Yes, but it will be easier to debug and the use of digitalRead(...), digitalWrite(...), and pinMode(...) makes the code more easily transferred to other types of Arduinos.

Good Luck!

Code: [Select]

const int CAMERA_PIN = 3;
const int SHUTTER_PIN = 4;
const int IN_PIN = 2;

//  These are times, specified in milliseconds.  Adjust as necessary.

const unsigned long ARMED        = 120000 ;
const unsigned long DISARMED     =    500 ;  //  Not specified, adjust as
                                             //  necessary.
const unsigned long SHUTTER_HOLD =    100 ;
const unsigned long CAMERA_HOLD  =   1000 ;

//  End of times.

/*
   Here is code for defining the states and making use of them,
   but there is a better way using enum that is shown lower down
   in a comment.
*/

const int SET_SHUTTER_LOW  = 100 ;
const int SET_CAMERA_HIGH  = 200 ;
const int WAIT_CAMERA_HIGH = 300 ;
const int SET_CAMERA_LOW   = 400 ;
const int WAIT_CAMERA_LOW  = 500 ;

const int MAKE_CAMERA_HIGH     = 1000 ;
const int MAKE_SHUTTER_HIGH    = 2000 ;
const int TIME_SHUTTER_HIGH    = 3000 ;
const int MAKE_SHUTTER_LOW     = 4000 ;
const int MAKE_CAMERA_LOW      = 5000 ;
const int TIME_CAMERA_LOW      = 6000 ;
const int NO_INTERRUPTION_YET  = 7000 ;

int loopState         = SET_SHUTTER_LOW  ;
int interruptionState = NO_INTERRUPTION_YET ;

/*
   End of code for defining the states and making use of them.
*/


/*
   Here is better code for defining the states and making use of them,
   and it has some advantages, but this code is more advanced and is
   therefore commented out.

  enum LoopStates {
  SET_SHUTTER_LOW,
  SET_CAMERA_HIGH, WAIT_CAMERA_HIGH,
  SET_CAMERA_LOW, WAIT_CAMERA_LOW
  } ;
  enum InterruptionStates {
  MAKE_CAMERA_HIGH, MAKE_SHUTTER_HIGH, TIME_SHUTTER_HIGH,
  MAKE_SHUTTER_LOW, MAKE_CAMERA_LOW, TIME_CAMERA_LOW,
  NO_INTERRUPTION_YET
  };

  LoopStates loopState = SET_SHUTTER_LOW ;
  InterruptionStates interruptionState = NO_INTERRUPTION_YET ;

   End of better code for defining the states and making use of them.

*/

unsigned long loopStartMillis ;
unsigned long interruptionStartMillis ;

void setup()
{
  pinMode(CAMERA_PIN, OUTPUT)  ;
  pinMode(SHUTTER_PIN, OUTPUT) ;
  digitalWrite(CAMERA_PIN, LOW)  ;
  digitalWrite(SHUTTER_PIN, LOW) ;

  pinMode(IN_PIN, INPUT);
  //  I am going to assume that there is a
  //  normally open (NO) pushbutton
  //  switch connected from this pin to the Vcc of the
  //  Arduino, and a pulldown resistor connected from
  //  this pin to ground (GND).
  //  Thus, there is an assumption that when the
  //  pushbutton is NOT pressed, this pin is LOW,
  //  and when the pushbutton is pressed,
  //  this pin is HIGH.

//  Serial.begin(115200) ;

}

void loop()
{
  unsigned long currentMillis = millis() ;  //  This variable is
                                            //  local to this function.
  switch (loopState) {
    case SET_SHUTTER_LOW:
      digitalWrite(SHUTTER_PIN, LOW) ;
      loopState = SET_CAMERA_HIGH ;
      break ;
    case SET_CAMERA_HIGH:
      digitalWrite(CAMERA_PIN, HIGH) ;
      loopStartMillis = currentMillis ;
      loopState = WAIT_CAMERA_HIGH ;
      break ;
    case WAIT_CAMERA_HIGH:
      if (currentMillis - loopStartMillis >= ARMED) {
        loopState = SET_CAMERA_LOW ;
      } else {
        while (triggered()) ;
      }
      break ;
    case SET_CAMERA_LOW:
      digitalWrite(CAMERA_PIN, LOW) ;
      loopStartMillis = currentMillis ;
      loopState = WAIT_CAMERA_LOW ;
      break ;
    case WAIT_CAMERA_LOW:
      if (currentMillis - loopStartMillis >= DISARMED) {
        loopState = SET_SHUTTER_LOW ;
      } else {
        //  Do nothing...  Keep waiting.
      }
      break ;
    default:
//    Serial.print("***** BAD loopState=") ;
//    Serial.println(loopState) ;
      while (true) ;  // Hang here forever, intentionally.
      break ;
  }
}

bool triggered() {
  unsigned long currentMillis = millis() ;  //  This variable is
                                            //  local to this function.
  bool result = false ;
  if ((interruptionState == NO_INTERRUPTION_YET) && (digitalRead(IN_PIN) == HIGH)) {
    interruptionState = MAKE_CAMERA_HIGH ;
    return true ;
  } else {
    switch (interruptionState) {
      case MAKE_CAMERA_HIGH:
        digitalWrite(CAMERA_PIN, HIGH) ; //  Unnecessary but harmless.
        interruptionState = MAKE_SHUTTER_HIGH ;
        result = true ;
        break ;
      case MAKE_SHUTTER_HIGH:
        digitalWrite(SHUTTER_PIN, HIGH) ;
        interruptionStartMillis = currentMillis ;
        interruptionState = TIME_SHUTTER_HIGH ;
        result = true ;
        break ;
      case TIME_SHUTTER_HIGH:
        if (currentMillis - interruptionStartMillis >= SHUTTER_HOLD) {
          interruptionState = MAKE_SHUTTER_LOW ;
        } else {
          //  Do nothing...  Keep waiting.
        }
        result = true ;
        break ;
      case MAKE_SHUTTER_LOW:
        digitalWrite(SHUTTER_PIN, LOW) ;
        interruptionState = MAKE_CAMERA_LOW ;
        result = true ;
        break ;
      case MAKE_CAMERA_LOW:
        digitalWrite(CAMERA_PIN, LOW) ;
        //  Requirements say to do
        //  this but it is
        //  in opposition to what the loop()
        //  function did ;
        interruptionStartMillis = currentMillis ;
        interruptionState = TIME_CAMERA_LOW ;
        result = true ;
        break ;
      case TIME_CAMERA_LOW:
        if (currentMillis - interruptionStartMillis >= CAMERA_HOLD) {
          digitalWrite(CAMERA_PIN, HIGH) ;
          interruptionState = NO_INTERRUPTION_YET ;
        } else {
          //  Do nothing...  Keep waiting.
        }
        result = true ;
        break ;
      case NO_INTERRUPTION_YET:
        result = false ;
        break ;
      default:
//      Serial.print("***** BAD interruptionState=") ;
//      Serial.println(interruptionState) ;
        while (true) ;  // Hang here forever, intentionally.
        break ;
    }
  }
  return result ;
}

Quoll

Thankyou so much, seriously this is a HUGE help. I am away from the project desk at the moment but will upload the sketch as soon as I can and make adjustments. This has been tricky for me as I am new to Arduino and am trying to work it all out.

Really looking forward to trying it out.

Thanks

Nathan
Nathan Litjens

Go Up