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

34 posts / 0 new
Last post

Pages

DrJones
DrJones's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany
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&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>0) {lastmode=mode; mode=0;}  //was on?  -> off, but remember the mode
        else mode=lastmode;                   //was off? -> 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<16 && mode>0) {           //really was a short press AND the light is on
          mode++; if (mode>=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&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>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<16) { // ** really was a short press mode++; if (mode>=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 } }
Edited by: DrJones on 08/26/2014 - 04:34
ChibiM
ChibiM's picture
Offline
Last seen: 14 hours 6 min ago
Joined: 05/09/2011 - 10:25
Posts: 6821
Location: Holland

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)

comfychair
comfychair's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

Bravo! Beer

pommie
Offline
Last seen: 5 months 2 weeks ago
Joined: 08/28/2013 - 03:56
Posts: 971
Location: Corio, Victoria, Australia

Thank you Beer

Cheers David

Nothing to see here folks, move along...

Sirius9
Sirius9's picture
Offline
Last seen: 7 hours 37 min ago
Joined: 03/04/2012 - 19:23
Posts: 4652
Location: South Europe

Nice work : -) thanks

 

comfychair
comfychair's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

(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

Hopback
Hopback's picture
Offline
Last seen: 5 years 2 months ago
Joined: 04/19/2012 - 15:32
Posts: 564
Location: West Sussex

Received my Minimo today!

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

Thank you Dr Jones. Big Smile

Pavithra_uk
Pavithra_uk's picture
Offline
Last seen: 1 week 5 days ago
Joined: 04/24/2012 - 22:47
Posts: 779
Location: SRI LANKA

nice Smile

comfychair
comfychair's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

http://75.65.123.78/6XL2/Dsc07018.jpg

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

ImA4Wheelr
Offline
Last seen: 4 months 1 week ago
Joined: 02/03/2013 - 14:51
Posts: 7935
Location: SC

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.

dthrckt
dthrckt's picture
Offline
Last seen: 4 days 9 hours ago
Joined: 11/08/2011 - 10:11
Posts: 4656
Location: Upstate NY
DrJones wrote:

…and decided (not lightly; I hope people still buy some drivers from me so I can buy some flashlights…) to share it.

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 Smile

ImA4Wheelr
Offline
Last seen: 4 months 1 week ago
Joined: 02/03/2013 - 14:51
Posts: 7935
Location: SC

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.

 

ImA4Wheelr
Offline
Last seen: 4 months 1 week ago
Joined: 02/03/2013 - 14:51
Posts: 7935
Location: SC

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.

Sirius9
Sirius9's picture
Offline
Last seen: 7 hours 37 min ago
Joined: 03/04/2012 - 19:23
Posts: 4652
Location: South Europe

ImA4Wheelr wrote:

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:

 

AlexTG
Offline
Last seen: 10 months 4 weeks ago
Joined: 10/29/2012 - 08:40
Posts: 202
Location: Kiev, Ukraine

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?

DrJones
DrJones's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

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.

 

 

 

ImA4Wheelr
Offline
Last seen: 4 months 1 week ago
Joined: 02/03/2013 - 14:51
Posts: 7935
Location: SC

Thank you Sirius9.  Smile

comfychair
comfychair's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

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.

Microa
Offline
Last seen: 9 hours 32 min ago
Joined: 06/29/2011 - 21:20
Posts: 251

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?

AlexTG wrote:
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
comfychair's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

Microa wrote:
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}.

Tom E
Tom E's picture
Offline
Last seen: 12 hours 14 min ago
Joined: 08/19/2012 - 08:23
Posts: 15042
Location: LI NY

Thanx Doc. I added some simple debouncing, sped up the long click a little (350 msecs), and am using these modes:

const byte modes[]={0, 5, 10, 81, 255 }; // 5=moonlight(2%), 10=4%, 81=32%, 255=100%

The debouncing is below. It just does 3 reads on the I/O pin with a 2 msec delay in between. I'm really not sure if it will do much because no idea if the time delay of 2 msecs is relevant with this hardware. I've seen other driver code that did much longer time delays, interrupt based.

  // Do some simple de-bouncing checks
  byte inPressed = ((PINB&8) == 0); // 0=not pressed
  if (inPressed)
  {
     _delay_ms (2);
     inPressed = ((PINB&8) == 0);
     if (inPressed)
     {
        _delay_ms (2);
        inPressed = ((PINB&8) == 0);
     }
  }

  if (inPressed)   // qualified button being pressed

    ...


This firmware seems to be working fine, but I tried it in my troublesome XP-11, and high mode is not working, but had the same problem with another e-switch version (Werner's), so thinking I might have messed up the LED or driver... I think I did have a short going in with the emitter, fixed it, but damage is probably done.

comfychair
comfychair's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

Sub-moonlight with PWM of '1', after adding a big fat toroid inline with LED+...

http://75.65.123.78/driverhacks/Dsc07123.jpg

http://75.65.123.78/6XL2/Dsc07073.jpg

I like these direct drive FETs much much better than 7135s.

ImA4Wheelr
Offline
Last seen: 4 months 1 week ago
Joined: 02/03/2013 - 14:51
Posts: 7935
Location: SC

Sweet Comfy.  For some reason that fat toroidal inductor reminds me of a slicks on the back of a rear wheel drive dragster.

mattthemuppet
Offline
Last seen: 8 months 2 days ago
Joined: 01/04/2012 - 16:20
Posts: 1273
Location: WA

you’re a star DrJones and thank you for having the courage to put your hard work out there, with nothing but thanks in return. I’ve been fretting about how to turn one of my commuter lights into an e-switch light as it’s out of action due to a crappy Judco switch and this pops up. Thank you so much, it’s much appreciated.

DrJones
DrJones's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Edited first post to add a "Werner's UI" variant of MiniMo.

WarHawk-AVG
WarHawk-AVG's picture
Offline
Last seen: 1 year 7 months ago
Joined: 01/04/2014 - 06:47
Posts: 5071
Location: H-Town

Awesome update DrJones...thanks

totilde
totilde's picture
Offline
Last seen: 5 months 2 weeks ago
Joined: 12/27/2012 - 12:22
Posts: 1157
Location: spain

I haven’t read this thread before. Thank you for sharing the results all your effort here for free. I’m planning to mod a light with an electronic switch, but I don’t have equipment nor knowledge to flash it myself, so I’ll take the easy route (buying one from you)
Thanks

Mooooooo

Microa
Offline
Last seen: 9 hours 32 min ago
Joined: 06/29/2011 - 21:20
Posts: 251

Dear Dr. Jones,
I am thinking that the code of MiniMo is small in size which may be possible to fit in the smallest Attiny family Attiny10. I modified the code ( change PORTB=8 to PORTB=4, (PINB&8) to (PINB&4) ) to set the PB2 of the Attiny10 as switch pin and then built the hex by AVR Studio 4 but the process was failed with 2 errors. Would you please help me to correct the errors.

Microa
Offline
Last seen: 9 hours 32 min ago
Joined: 06/29/2011 - 21:20
Posts: 251

After I have installed the AVR-toolchain-3.4.2, the hex file can be built now.

DrJones
DrJones's picture
Offline
Last seen: 5 years 8 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Sorry I was of no help, but I never worked with an ATtiny10. No EEPROM and different programming interface made me not investigating them further.

Microa
Offline
Last seen: 9 hours 32 min ago
Joined: 06/29/2011 - 21:20
Posts: 251

Thanks for your advice. I found that the Attiny13A-MMU has the same footprint as Attiny10. It is not worth for the effort to work with an Attiny10 to replace Attiny13A.

Pages