Flashlight mode selection through power switch

Most popular high powered LED flashlights have mode selection by “half pressing” the main power button. I am trying to accomplish this. I’ve designed a circuit using a ATTiny85 ( I can change this if there is something better suited), to control an LED driver. The driver works, just need help with the firmware. I’d attach a schematic, but simple and there’s just a few components to it, the micro, a capacitor and pull up resistor for the “mode selection” pin.

My question is that I can’t seem to get this design to change modes, it only powers off and then back on again. Can anyone provide some sample code of a typical mode changing flashlight so I can see how this works?

I’ve attached what I’m using thus far. I am guessing that the “Half press” is simply something that micro detects as temporary voltage drop within a short time period as a capacitor discharges? It would be nice to not use a giant capacitor and have the micro detect the on/off action as the button press itself. Any ideas?

Thanks!

flashlight attiny85.txt (2.99 KB)

Please post your code using code tags if you want to increase the chance of anyone looking at your code. You should also post some information about what hardware you are using.

In order to reach your goal, you either need a switch with multiple states or a switch with some sort of variable resistance in it.

Such a torch will have a micro-power microcontroller that's permanently powered up, probably running on an internal low-frequency oscillator for ultra-low power consumption. The "power" switch is just a push button, its all done in software.

If the (pulled up) input pin goes low for less than a given threshold, change the mode. If it goes low for longer, toggle on/off the flashligh. That should be simple enough to code, but I'm not sure that is what OP is looking for..

If the (pulled up) input pin goes low for less than a given threshold, change the mode. If it goes low for longer, toggle on/off the flashlight. That should be simple enough to code, but I’m not sure that is what OP is looking for…

Sounds like this is what I’m looking for. I have about a dozen different torches/flashlights that run off 18650 cells, and all of the endcap buttons are on/off to the battery, so a constant on driver isn’t necessary.

Here’s what I have so far, just not sure how to get it to recognize going low to change modes before the switch opens (to turn it off).

#include <avr/sleep.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

//**here you set brightness of modes
int mode1 = 255;
int mode2 = 8; 

const int buttonPin = 1; //setting button pin
const int ledPin =  0;  // setting LED pin
int buttonPushCounter1 = 1;    // counts the button pushes
int buttonState1 = 1;    // tracks the button state
int lastButtonState1 = 0;    // last state of the button  
int buttonState = 0;  // Button status
int lastButtonState = LOW;  //Button set to LOW

long lastDebounceTime = 0;  // Debounce status
long debounceDelay = 50;  // Debounce timer

void setup() {
  pinMode(ledPin, OUTPUT);  // Sets LED as output
  pinMode(buttonPin, INPUT);  // Sets button as input

  sbi(GIMSK,PCIE); // Turn on Pin Change interrupt
  sbi(PCMSK,PCINT1); // Which pins are affected by the interrupt
}

//mode one: LED is set to 100% brightness by default 
int modeone() {
  analogWrite(ledPin,mode1);
}

//mode two: LED is set to your preference of brightness (my default is about 30% = 76)
int modetwo() {
  analogWrite(ledPin,mode2);
}

//mode three: strobe light, I set it to be the most disorienting in darkness but feel free to change on and off times (in [ms])
int modethree() {
  digitalWrite(ledPin,HIGH);
  delay(15);
  digitalWrite(ledPin,LOW);
  delay(100);
}

//Sleep mode
int modefour() {
  analogWrite(ledPin,8);
  delay(20);
  analogWrite(ledPin,0);
  delay(20);
  analogWrite(ledPin,8);
  delay(20);
  analogWrite(ledPin,0);
  delay(20);
  analogWrite(ledPin,8);
  delay(20);
  analogWrite(ledPin,0);
  buttonPushCounter1 = 1;
  system_sleep();
  
}
  
void loop() {
  // All the debound button press stuff
  int reading = digitalRead(buttonPin);
  buttonState1 = digitalRead(buttonPin);
  
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {

    if (reading != buttonState) {
      buttonState = reading;
      
        if (buttonState1 != lastButtonState1) {
          
          if (buttonState1 == HIGH) {
            buttonPushCounter1++;
            
            if (buttonPushCounter1 == 5) {
              buttonPushCounter1 = 1;}
          }
          else {
          }
        }
          lastButtonState1 = buttonState1;
    }
  }
  lastButtonState = reading;

//switching modes:
  
  if (buttonPushCounter1 == 1) {  
      modeone();
}
  if (buttonPushCounter1 == 2) {  
       modetwo(); 
}
  if (buttonPushCounter1 == 3) {  
      modethree();
}
  if (buttonPushCounter1 == 4) {  
      modefour();
}

}
//loop end


void system_sleep() {
  cbi(ADCSRA,ADEN); // Switch Analog to Digital converter OFF
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
  sleep_mode(); // System sleeps here
  sbi(ADCSRA,ADEN);  // Switch Analog to Digital converter ON
}

ISR(PCINT0_vect) {
}

I suspect the main on/off powers up the internal circuity, which enables an internal "decade" type chip (4017B?). I've used these type chips years ago to make a simple video switcher. Each time the input pin is clocked, the output is moved to the next pin. If the flashlight has a similar chip, then you might clock the input pin to switch the flashlight mode.

technosteve:
Sounds like this is what I'm looking for. I have about a dozen different torches/flashlights that run off 18650 cells, and all of the endcap buttons are on/off to the battery, so a constant on driver isn't necessary.

So the physical button on the torch is the type that, when half pressed is on - and off if released again. If the button is fully pressed, it makes a click and stays on until fully pressed with a click again?

If that is the case, I do not think that you will be able to detect if the switch is half or fully pressed - but I'm not sure since I've never played with a switch of that type. Eventually the code would be the same for either type of switch and it would look something like this:

loop()
{
  button = read_button_state()

  if (button is pressed) and (button_state is released) then begin

    button_activated = current_millis

  end else if (button_state is pressed) and (current_millis - button_activated > mode_threshold) then begin

    toggle_torch_on_off()

  end else if (button is released) and (button_state is pressed) and (current_millis - button_activated > debounce_time) then begin

    next_torch_mode()

  end

  button_state = button
}

The pseudo code above has a flaw, but you will flicker that out! :wink:

"So the physical button on the torch is the type that, when half pressed is on - and off if released again. If the button is fully pressed, it makes a click and stays on until fully pressed with a click again?"

No, the button has a position that toggles the beam type before the button is fully clicked.

zoomkat:
No, the button has a position that toggles the beam type before the button is fully clicked.

Sigh… :confused:

So the physical button on the torch is the type that, when half pressed is on - and off if released again. If the button is fully pressed, it makes a click and stays on until fully pressed with a click again?

There is only one button on the entire unit, which is a single pole switch/button, nothing fancy. A "Half press" is simply an momentary opening of the switch. If this is done fast enough, say around 250ms for example, then it serves to trigger a mode change, any longer and the flashlight will just shut off and resume the previous mode once the momentary press goes back to the closed state (flashlight on).

The example code by Danois90 has promise, but I'm not sure how to integrate it into what I have. I think I can add a capacitor to allow the micro to have power for the 250ms duration to sense if the button closes within that time period.

Make sense?

technosteve:
I think I can add a capacitor to allow the micro to have power for the 250ms duration to sense if the button closes within that time period.

So, the chip (ATtiny85) only receives power, when the button is pressed or what? My previous example assumes that the chip is always powered on..

If you google you might find information on modifying the flashlight switches. I think I've seen info in the past on defeating the various touch positions.

Here are some facts to clarify:

The button just completes the circuit of the battery providing all electronics power.

The button doesn't have modes, its simply on/off, with a "half press" momentarily opening the switch.

If the button is off, it's the same as removing the batteries from the flashlight.
If the button is half-pressed, it's the same as removing the batteries from the flashlight.
If the button is turned on, all components (driver and microprocessor) get power.

The button only has 2 positions.
1 = on
2 = off

The button does not have various positions.

The button does not need to be modified. The firmware needs to be modified.

The microchip is only powered when the button is on.

The microchip is not constantly under power when the button is off.

I'm not trying to defeat the modes, I'm trying to utilize them.

This is the way almost every popular mode changing flashlight works, so I'm confident I can get this to work, I'm just not sure how.

Thanks for your help.

"The button doesn't have modes, its simply on/off, with a "half press" momentarily opening the switch."

Sounds like a soup sandwich. I have a couple of the high output flashlights with the multi switches and find them to be a PITA when you need light right now. I'm curious as to how the switching sequence is remembered in the switch internals if the momentary "off" position really interrupts the battery power to all components. A fairly simple experiment to further study the mechanics would be to remove the end switch and then jumper it back into the circuit using some test leads. Turn the flashlight on using the switch, then remove and replace the jumper and see if the flashlight continues to cycle thru its program, or starts back at an initial on position. There might be capacitors internal to the switch to hold memory for a while, but that might not be the case.

Thank you for the clarification, but.. Opening a switch means preventing current to flow through it, closing a switch means that current can flow and whatever the switch is switching is powered on. Momentarily means a very short period of time.

If half-pressing the switch closes the switch for a very short time, then I cannot see how your approach could work. The ATtiny needs a little time to boot and a capacitor needs a little time to charge. If half-pressing the switch does not allow enough current to flow, the MCU will not be able to do the work you want from it.

Thank you for the clarification, but.. Opening a switch means preventing current to flow through it, closing a switch means that current can flow and whatever the switch is switching is powered on. Momentarily means a very short period of time.

I agree and feel that I've used those terms correctly in my previous posts.

If half-pressing the switch closes the switch for a very short time

As I previously indicated, a half-press momentarily opens the circuit. A capacitor on the board maintains an adequate charge to keep the MCU alive for about .5 seconds, so no boot period is required if the half press is shorter than that.