How to select different Modes with push button

I building a camera shutter controller with different modes (IR detection, Sound etc) and want to use a single push button to select between the "modes". When a mode is select it must then run the code associate with it.

I wrote the code with the help of the Internet to select between the different mode but having problems executing the individual modes. It only runs the mode a single time and then stop until i select the next mode. My Mode selection is using the break command after each mode. I think this is why it stop after the break. What is the basic flow I have to follow to do this.

Onced I have selected a mode it must run that mode code until the push button is pressed and then move on to the next mode running it, etc.

Any suggestions will be highly appreciated

It's hard to tell anything without seeing your code.

This is a shorten version of the code. The print line only for help. The problem is it doesn't continue with the subroutine, but wait for the push button, because of the break command. I don't know ho to fix this.

/*Push BUTTON to switch through Modes */

boolean boItWasOn;
boolean boItIsOn;

#define ledPin0 13
#define ledPin1 12
#define LASER_THRESHHOLD 400
#define CAMERA_SHUTTER_PIN 3
#define LASER_PIN 5
#define LASER_TRIGGER_ANALOG_PIN 0
#define Sw0 8 /* Configure the program to look at digital Sw0 */

int potPin = 1; // select the input pin for the potentiometer
int valA = 0; // variable to store the value coming from the IR sensor

byte bCount=1;

void setup()
{
/Start, second block of things for tkbOutput/
pinMode(ledPin0, OUTPUT);
pinMode(ledPin1, OUTPUT);
pinMode(CAMERA_SHUTTER_PIN, OUTPUT); //declare the SHUTTER as Output
digitalWrite(CAMERA_SHUTTER_PIN, LOW); //Set SHUTTER pin LOW
pinMode(LASER_PIN, OUTPUT); //declare LASER pin as a Output
digitalWrite(LASER_PIN, HIGH); // Turn on the Laser

//Establish initial LED states... all off....
writeLEDs(0,0);

// Next set the state of boItWasOn according to the state of things at the outset....

boItWasOn=boSw0();

Serial.begin(9600); // open serial
}

void loop()
{
waitForChange();//Watches Sw0; changes boItWasOn and boItIsOn
delay(300); //debounce
waitForChange(); //Watches Sw0; changes boItWasOn and boItIsOn
writeNumber(bCount);
delay(300); //debounce
bCount++; //add 1
if (bCount==4){bCount=0;}; //switch back to 0 at number of counts
}

boolean boSw0()
{

return digitalRead(Sw0);
}

void writeLEDs(byte b1, byte b0)
{
digitalWrite(ledPin1,b1);
digitalWrite(ledPin0,b0);
}

void waitForChange()
{

do {
boItIsOn=boSw0();
}
while (not(boItWasOn xor boItIsOn));
boItWasOn=boItIsOn;
}

void writeNumber(byte bToWrite)
{
switch (bToWrite)
{
case 0:{writeLEDs(0,0); Serial.println("Sound Mode");break;} // Sound
case 1:{writeLEDs(0,1); Serial.println("IR Mode");break;} // Infrared detector
case 2:{writeLEDs(1,0); Serial.println("IR Mode (Break the beam to trigger shutter)");IRMODE();break;}//

I.R.
case 3:{writeLEDs(1,1); Serial.println("Lightning Mode");break;} // Lightning

}
}
void IRMODE() //Subroutine for case 2, each case will have its own subroutine
{
valA = analogRead(potPin); // read the value from the pot
int laserVal;

laserVal = analogRead(LASER_TRIGGER_ANALOG_PIN);
if (laserVal > LASER_THRESHHOLD)
{
digitalWrite(LASER_PIN, LOW); // Turn off the Laser
delay(valA); //delay acording to POT adjusment
digitalWrite(CAMERA_SHUTTER_PIN, HIGH);
Serial.println("SHUTTTER");
digitalWrite(LASER_PIN, HIGH); // Turn on the Laser
delay(500); // Keep it on for aligning of the Laser
Serial.println(laserVal, DEC);
}
}

How about a simple counter for each time the key is pressed.

if key pressed.
counter is incremented.
if counter is larger than total number of modes set back to 1.
run the code for the mode matching the value of the counter.
loop back.

I did this to switch between display screens on an lcd on the project Im working on at the moment.
When the counter value is 1, run the procedure to display screen 1.
When the counter value is 2, run the procedure to display screen 2.
....I had 4 screens. So when the value got to 5 I set it to 1.

Gordon

Gordon

Thanks, for the advise. Tried it and it is working. Need to finalize the rest

No I run in to trouble!!! Don't think there will be a solution, but maybe.

I use a adjustable delay to delay the shutter or flash after a sensor sense. As this is in a continuous loop, during the delay the circuit doesn't respond to the push button. So it's a hit and trail effort to push the button at the right time.

What to do????

In my project I needed to have the keys a bit more responsive as well.
So I used the metro library to call the button checking procedure every 250 milliseconds and the procedure to display the information on the lcd every 1 second.
So this obviously biased the application timing towards the button checking making it more responsive.

Have a look at my earlier post about the Metro library here:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1224854557/4#4

Is that any good for you?

Gordon

Use millis() instead of delay so that the code isn't stopped and thus the circuit responds at all times.

Lazer57

Thanks
I am trying that, but are struggling with the code.
Something like this, ???

if (millis() - previousMillis > interval) {
digitalWrite(ledPinA, HIGH);

Sukkelaar (Someone who is struggling)

Thats just what the Metro library does but wraps it up in a nice OO package.

So you create an instance of the Metro object for each of the events you want to time.
Then check each of the instances to see if they are to be triggered within your loop.
Its a very light weight library so not an issue of bloat with extra libraries.

http://www.arduino.cc/playground/Code/Metro
What it doesnt specifically say, in the documentation, is you can create an instance for each of the events you want to time.

Please excuse my pseudo code.

Creating the instances
Metro modeMetro = Metro(1000); // 1 second
Metro keyMetro = Metro(250); // 250 milliseconds

and in the loop()
if (modeMetro.check() == 1){
DoYourModeStuff();
}
if (keyMetro.check() == 1){
CheckForKeyPress();
}

So it handles all the millis counting and intervals for you and all you have to do is check if its time with the .check function.

Gordon

You could do what GordonEndersby proposed, only modifying so that it uses interrupts. and ofcourse millis() not delay():

if key goes high trigger interrupt
counter is incremented.
if counter is larger than total number of modes set back to 1.
run the code for the mode matching the value of the counter, using millis for timing
loop back.

Lazer57

Thanks
I am trying that, but are struggling with the code.
Something like this, ???

if (millis() - previousMillis > interval) {
digitalWrite(ledPinA, HIGH);

yea, something like that would work. for the times that you have a constant delay (like 300ms in your code), you could replace "interval" with 300).

please take into account that i am very new to all of this, less than 2 weeks. so if you can understand the more veteran members responses it would probably be best to go with their suggestions.

good luck.

I have tried the delay with millis() and it is working. It responds excellent to the push buttons but because it runs the complete loop again it is not working as planned.

I think I will have to loop in a specific mode and while in that loop during the delay using millis() look at the Mode Select Push Button.

Maybe Gordon suggestion will work but I am a little bit lost. Still new to me this software stuff. With the hardware I have no problems.

Hi I got my program working. Thanks for the advise.

I also manage to use the same push button to enable the camera (long duration) after I select a Mode (brief press). Now I need to assemble everything.

I am using LED's to indicate what Mode is selected. With 7 different modes this is not elegant. Need to use and LCD display. Tried the Nokia 3310 but no luck so far. The dam thing stays dead. Copy the sketch from this forums did the wiring all to no avail.

I only need to show the modes and then maybe a running readout of the sensor (Sound/IR) value. The LCD can also be handy in displaying the set delay time before shutter release. Any suggestions in what type of LCD will be the easiest

The Nokia LCD is working, only after I put a capacitor on pin 7 Vout of LCD. used a 1uf.