other drivers

MiniDrv (for clicky switches)

Someone asked me for a simple firmware, easy to understand, so I wrote this firmware, and thought I could share it. I named it MiniDrv (as in minimalistic driver) - it only has 18 lines of code (not counting comments). No battery monitoring though.

License: CC0 (Creative Commons - completely free)

//minimalistic driver firmware (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 
uint8_t modes[]={8,90,255};              //PWM values, 6..255  (6 may be too low though, depends on driver hardware)
int main() {
  DDRB=2;                                //define PB1 as output
  TCCR0A=32+3; TCCR0B=1;                 //PWM setup, 18kHz
  EEARL=4;EECR=1; uint8_t mode=EEDR;     //read from EEPROM
  if(mode>=sizeof(modes)) mode=0;        //check if invalid
  OCR0B=modes[mode];                     //set PWM level
  EEDR=mode+1;                           //next mode
  if(EEDR>=sizeof(modes)) EEDR=0;        //wrap around
  EECR=4;EECR=4+2;  while(EECR&2);       //write to EEPROM
  _delay_ms(1000);                       //delay for memory (or no-memory) to kick in
  EEDR=mode;                             //memory: use this mode again   \  use one of these lines
  //EEDR=0;                                //no memory: restart from 0   /  use one of these lines
  EECR=4;EECR=4+2;  while(EECR&2);       //write to EEPROM
  while(1) {}                            //endless loop
}
Uses 18kHz PWM, which may be a problem with FET drivers. To use 9kHz PWM change TCCR0A=32+3; to TCCR0A=32+1;.

MiniMo (momentary switches)

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).

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 (wrapping around) when on.

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

License: CC0 (Creative Commons - completely free)

//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, 6..255 - LEAVE THE "0" THERE
int main() {
  DDRB=2; PORTB=8;                       //define PB1 as output and pull-up switch on PB3
  TCCR0A=32+3; TCCR0B=1;                 //PWM setup, 18kHz
  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) {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, wrap around
        }
        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
  }
}

As MiniDrv above this uses 18kHz PWM, which may be a problem with FET drivers. To use 9kHz PWM change TCCR0A=32+3; to TCCR0A=32+1;.

It doesn't us a sleep mode when "off", so the standby current is somewhat unpleasant (~2mA, depletes a full 18650 in about 2 months).

MiniMo up&down variant

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 to cycle through) 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.

//MiniMo up&down variant -- 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=32+3; TCCR0B=1;                 //PWM setup, 18kHz
  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 (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, wrap around including 'off'
        }
        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
  }
}

© DrJones (2014)