MiniMo - simple firmware for momentary (electronic) switches (source code)

Lights with electronic switches are becoming quite popular, I also like them, because they give more flexibility regarding the UI. Similar to MiniDrv, a small firmware for clickies, I made a minimalistic firmware for momentary buttons, named it MiniMo (MINImalistic driver for MOmentary switches) and decided (not lightly; I hope people still buy some drivers from me so I can buy some flashlights...) to share it.

The UI is simple but consistent: A long press (>0.4s, so it's not that long) switches the light on and off (with memory), a short press switches to the next mode (circular) when on.

To configure, just add/delete/edit the values in the modes[]={...} line.

//MiniMo -- minimalistic driver firmware for momentary buttons (no blinkies)  --  DrJones 2014
#define F_CPU 4800000                    //use fuses  low:0x75  high:0xff
#include <avr/io.h>
#include <util/delay.h>
//change modes here; just change/add/delete values. The "0" is 'off' 
uint8_t modes[]={0,  8,90,255};          //PWM values, 5..255 - LEAVE THE "0" THERE
int main() {
  DDRB=2; PORTB=8;                       //define PB1 as output and pull-up switch on PB3
  TCCR0A=0b00100001; TCCR0B=0b00000001;  //PWM setup, 9kHz
  uint8_t count=0,mode=0,lastmode=1,waspressed=0; //define some variables used below

while(1) { //endless loop

if ((PINB&amp;8)==0) {                   //when the button is pressed (PB3 pulled down)
  count++;                           //count length of button press
  if (count==16) {                    //pressed long (8*50ms)
    if (mode&gt;0) {lastmode=mode; mode=0;}  //was on?  -&gt; off, but remember the mode
    else mode=lastmode;                   //was off? -&gt; on, with previous mode.
  }
  waspressed=1;                      //remember that the button was pressed, see below
}
else {                               //button not pressed
  if (waspressed) {                    //but it was pressed, so it has just been released!
    waspressed=0;                      //reset that
    if (count&lt;16 &amp;&amp; mode&gt;0) {           //really was a short press AND the light is on
      mode++; if (mode&gt;=sizeof(modes)) mode=1; //next mode
    }
    count=0;                           //reset counter
  }
}    

OCR0B=modes[mode]; //set PWM level (0 is off)
_delay_ms(25); //wait a bit before checking again, important for counting
}
}

I think this may help a couple of projects here.

License: CC

EDIT Since people seem to like Werner's UI (short press for next mode, long press for previous mode, like in mobydrv; but OFF is just one of these modes) and since it is already implemented elsewhere, i thought I'd just show how easily it can be implemented in MiniMo, too. Only 4 lines had to be edited, marked with **, and the lastmode variable declaration was omitted.

I also changed the timing a bit (25ms delay in the main loop) to make it respond a bit quicker.

//MiniMo -- minimalistic driver firmware for momentary buttons (no blinkies)  --  DrJones 2014
//Up&Down variant ("Werner's UI")
#define F_CPU 4800000                    //use fuses  low:0x75  high:0xff
#include <avr/io.h>
#include <util/delay.h>
//change modes here; just change/add/delete values. The "0" is 'off' 
uint8_t modes[]={0,  8,90,255};          //PWM values, 5..255 - LEAVE THE "0" THERE
int main() {
  DDRB=2; PORTB=8;                       //define PB1 as output and pull-up switch on PB3
  TCCR0A=0b00100001; TCCR0B=0b00000001;  //PWM setup, 9kHz
  uint8_t count=0,mode=0,waspressed=0;   //define some variables used below

while(1) { //endless loop

if ((PINB&amp;8)==0) {                   //when the button is pressed (PB3 pulled down)
  count++;                           //count length of button press
  if (count==16) {                   //pressed long (16*25ms=0.4s)
    if (mode&gt;0)  mode--;             // ** decrease mode
    else mode=sizeof(modes)-1;       // ** wraparound
  }
  waspressed=1;                      //remember that the button was pressed, see below
}
else {                               //button not pressed
  if (waspressed) {                    //but it was pressed, so it has just been released!
    waspressed=0;                      //reset that
    if (count&lt;16) {                  // ** really was a short press
      mode++; if (mode&gt;=sizeof(modes)) mode=0; // ** next mode
    }
    count=0;                           //reset counter
  }
}    

OCR0B=modes[mode]; //set PWM level (0 is off)
_delay_ms(25); //wait a bit before checking again, important for counting
}
}

Thanks Dr Jones for your great contribution to the flashlight world!! Highly appreciated.

I'm not going to use it, because I have no side clickers that need a special code, but I guess this could be a replacement for some lights. (Even branded)

Bravo! :beer:

Thank you :beer:

Cheers David

Nice work : -) thanks

(Only 4 replies? Seriously guys?!)

  DDRB=2; PORTB=8;                       //define PB1 as output and pull-up switch on PB3

I have one with the switch wired to the third star/PB4 but the wire's hidden under JB Weld (d'oh!), what does that line need to be changed to to switch the input pin from PB3 to PB4? I tried random numbers, but couldn't get it to work. (I temporarily rednecked it by bridging pins 2 & 3 with solder) xD

Received my Minimo today!

Once Iā€™ve done my chores, I will break out the soldering iron and play!

Thank you Dr Jones. :smiley:

nice :slight_smile:

3x XM-L2 T6 3B, 15-amp SRK clone driver, PWM values of 0,1,3,8,20,50,120,255

Gives totally unscientific bathroom ceiling bounce lux numbers of:
0.3
1.8
6.4
17.9
47.6
116.8
241

Comfy is right in Post 5. Thank you very much for the generosity of sharing this code DrJones. I look forward to trying it soon.

have you considered soliciting/accepting ā€˜donationsā€™ from those who use the code?

I just bought a few drivers and Iā€™m planning to use your firmware. Rather than purchase drivers from you, Iā€™m forcing myself to learn how to flash them, with an eye toward eventually learning to modify the codeā€¦ā€¦.but I have no problem compensating you for your ingenuity.

Another reason for doing it myself - Iā€™m having a little trouble deciding which firmware to use (from just reading the text descriptions), so I want to experiment with each. I might also draw flow diagrams for your UIs at some point.

Oh, and thanks for this new addition :slight_smile:

That's a good idea Dthrckt. I'm sure I will eventually be using this code in some of my lights. I would feel better about it that way.

Anyone know what pins are the momentary switch? I can pull up the Attiny13a data sheet and compare it to the code, but I'm hoping someone already knows.

I presume its star 4, same as for lumodrv or mobydrv:

Thank you DrJones for the code!

Do I understand correctly - If I want to get rid of last mode memory and make the light always start on certain mode, I should change the code something like this:

if (mode>0) mode=0;          //was on?  -> off
else mode=2;                      //was off? -> on, start on Med

(might also skip the ā€œlastmodeā€ variable in the definitions)

Right?

comfychair: For a switch on PB4 use "PORTB=16;" there and "if ((PINB&16)==0)" some lines below.

AlexTG: Yes, exactly.

BTW: The minimum value of 5 in the modes[] is a quite safe value for an AMC7135-based driver; 4 might work, too. For drivers with a FET or a buck driver, even lower values may work.

Thank you Sirius9.

Yep, the low-low values 1 2 & 3 didn't work with 7135s when I tried it, only starts to light up at 4. But on the FET drivers even 1 works fine.

Dear DrJones,
Thanks for your sharing of the code.
If I understand correctly that mode=1 -> 8, mode=2 90, mode=3>255. I mean the position of the PWM levels in the line uint8_t modes={0, 8,90,255}; Am I correct?

Yep. Compare that line in the original to this one: http://75.65.123.78/fw/minimo-7mode-pb4.txt

You can also switch it to descending instead of ascending. {0,8,90,255} vs. {0,255,90,8}.