alexvh's firmware. Update: Hidden strobe, Ramping and optional mode memory added.

Thanks for the additional info DrJones. This sounds like it may be an effective dodge for the Tiny10’s lack of EEPROM (offtime / no memory with high-value voltage divider resistors).

That said, who wants to fool with the Tiny10? :~

I think it is also not possible to tune offtime periods in firmware with this method. With the OTC method those who do flashing can easily tune the values if desired.

Here's my code with memory, based on MiniDrv:

#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, 5…255

#define NOINIT attribute ((section (".noinit")))

volatile NOINIT uint16_t cookie;

int main() {

DDRB=2; //define PB1 as output

EEARL=4;EECR=1; uint8_t mode=EEDR; //read from EEPROM

if (cookie==1338) {
mode++;
}
//else mode=0; //NOMEM
cookie=1338;

if(mode>=sizeof(modes)) mode=0; //wraparound, also check if invalid
EEDR=mode; EECR=4;EECR=4+2; while(EECR&2); //write mode to EEPROM

uint8_t lvl=modes[mode];
TCCR0A=0b00100001; TCCR0B=0b00000001; //PWM setup, 9kHz
OCR0B=lvl; //set PWM level

while(1) {} //endless loop
}

Do you have a way of measuring how much off time you can have before the cookie expires? I’ve found I can get about 500ms of off time before the memory decays with the capacitor on the 101 driver (I measured it to be about 10uF). If I swap it with one from a 105C driver (about 5uF) I find I can still get about 400ms. When I’m using my flashlight normally, I find I press the switch for 200-300ms. I find that this method works fine for me. I’ve been using it in my flashlight for a little while now and I’m happy with it.

I’m curious if you found it was too small based on personal preference, or if the max off time was just shorter in your experiments.

On my drivers with pics I’ve seen greater than 10 seconds. This is without a voltage divider, so there’s no significant drain on the capacitor. Usually I tune the time to be where I want by adding a resistor in parallel with the cap. My normal combination is 2.2uF and 150k for about a half second timeout, which is my personal preference for this type of UI

Warning very basic question (I’m not really using Atmel studio at all anymore)… Where do you find / add the include files? Or does 6.2 do that all on its own at compile time?

That’s the purpose of the includes. They are brought in at compile time by the compiler. This is a pretty universal thing, not limited to Atmel studio or even to the C programming language family. Include directive - Wikipedia

Yea I get what they are, PIC used them in EVERYTHING (MPLAB 8.x) but you have to manually add them to the project tree. So in AS6.2 you don’t have to do anything at all but name them and the compiler handles looking them up?

Sure. I’ve never had to do anything manual to get includes working… in Atmel Studio, in other IDE’s, on the CLI, etc… it’s strange to me that MPLAB requires you to do something special to get includes to work… but sure enough, Google shows exactly the kind of thing you are talking about… Set The Include Directory Path - Developer Help

Just bumping the thread so people can see my update at the top. Ramping and optional mode memory added to firmware.

Thanks, I’ll take a closer look very soon!

Thanks. I’ll give this a run through AVR Studio to see if I have the same problem as before.

I’m hoping that problem was fixed by making the variables that are held after a power off volatile. It should prevent the compiler from doing optimizations that stop the trick from working.

I tried this on a different driver, a FET-based one designed by BLF members. It works! The lows aren’t low enough on a FET, and the ramp shape is a little weird, but the off-time memory seems to work as intended.

I will probably try using this technique on some of my non-OTC lights, since it seems like a solid improvement over “short-cycle” on-time memory.

Also, I added this code into my repository, linked in my sig below. Thanks for making it GPL! :slight_smile:

FWIW, I adapted this technique into my brass-edc.c firmware just now, and it seems to work well.

Additionally, it reduced the size of the ROM by 262 bytes! Now I have more than a quarter of the ROM to play with if I want (it went from 1018 bytes down to 756). This method allowed me to remove everything related to the WDT, eeprom, wear levelling, and the “short cycle” memory bit.

It’d be better if it could detect short/med/long presses instead of just short/long, but it’s still a big improvement over on-time memory. :slight_smile:

(I’m particularly happy about this, because I wanted off-time mem on this light but it doesn’t have enough room to add a capacitor and still be able to reflash it or fit a battery)

I found short-cycle still useful with off-time memory: have memory, but no need to cycle through all modes.

Could you elaborate on that?

I could see short-cycle being really useful for lights which are configurable via button presses, or as a shortcut back to mode 0 when “long press” isn’t mapped to that. Or generally for increasing the inputs from “long/short” to something deeper… “short(off)-short(on) / short-long / long-short / long-long”. But I don’t know specifically what you do with it.

With normal (off-time) memory, a tap cycles through all modes, while with short-cycle (off-time) memory, a single tap restarts at the first mode, and only consecutive taps switch through the modes; i.e. long-off -> memory; long-on, short-off ->mode 0 ; short-on,short-off ->next ; (and I actually found it comfortable to additionally have long-off, short-on, short-off -> mode 0, too).

Okay, that makes sense. I pretty much always prefer no memory on clickies, so I have “long-off -> mode 0” and “short-off -> next”. Or for on-time memory, “long-on,tap -> mode 0” and “short-on,tap -> next”. I haven’t ever felt a need for both.

The main thing I change with an off-time cap is to add a “medium-off” action, which either goes to the previous mode (if mode > 0 ) or to a sequence of hidden modes (if mode <= 0 ). It’s nice as a shortcut to turbo or battery-check.

For e-switches though… memory can be pretty nice. From off I’ll usually do “long-press -> moon”, “short-press -> memorized mode”, and “double-press -> turbo”. I like the instant access to all three.

You can of course just ramp up linearly by incrementing the pwm in a loop with a delay, I might add this. I used an array because I liked the smooth ramping, you can tell when you are near the max or min brightness because it is increasing or decreasing more slowly (also, I just think it looks cool). You might prefer the SQUARED ramp profile. If anyone has any ideas for different ramping profiles I’d be interested in trying them. Or if someone wants a different min or max in the ramp I could add that to the firmware.

On that topic, see ramp_calc.py and Ramping_UI_table.c in my firmware collection:

http://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/files/head:/ToyKeeper/Ferrero_Rocher/

It implements a few different ramp curves, but it requires an e-switch to work properly. My favorite is logarithmic, but cubic is closer to visually-linear. Also, it can optionally smooth out the lowest few levels by using PFM in addition to PWM, but this extra-low part of the curve has a different shape than the rest and is intensely voltage-sensitive.

I haven’t attempted to do ramping on a clicky switch light, because the interface is awkward and I didn’t like the idea of grinding through eeprom write cycles while it ramps. You solved the eeprom issue, but the UI is still a concern.

Anyway, I’ve been playing with my new no-OTC off-time light (ToyKeeper/s7/brass-edc.c) for a couple hours now and I’m really happy with it. Thanks!