After reading the code samples again, I’ve noticed a few things that might help to improve it further and some other random thoughts:
Sleep while looping! Running 9.6MHz cpu with ADC etc running consumes something like 4-5mA. Put the cpu in sleep while looping and wake up with adc interrupt (or add another wakeup source such as timer to wake you up before the watchdog). Especially if you use very low led currents like 5-10mA or so, this really makes a difference in the run time! (A single sleep-command at the end of the loop implements this.) Lowering cpu clock lowers power consuption too: running at 4.8MHz roughly halves power from 9.6MHz and so on.
Oh, as soon as the light is really low and time to turn off, it should turn off watchdog and go to a deep sleep. This would keep the power consuption in the microamp range and leaving it on for a few days should be no problem. Brownout detector should/could be used too but unfortunately only the voltage levels are not too convinient (1.8V + a diode drop at low current is better than nothing, 2.7V level is of no use)
Glitches: If you get glitches by eg. a bumping battery with bad contact while running/cycling on a rough surface you might get low-bat readings that are not real. Once you detected it the lowering of the power is permanent. You can always tackle this with more measurements. Yet better would be a fallback that raises the current up if the battery is later found not to be empty after all. Generally I’d not trust Atmel ADC to be too reliable and noice free in any environment without some filtering/averaging.
Spurious mode changed has been a problem in some environments and it is just an extreme example glitch. I’ve always wondered about methods to detect a power failure early on and shutting the light down (with cpu sleeping) for a few milliseconds. This might help surviving short power outages especially when running at high currents. (This gets very complicated matter without hardware changes when you think more about it. Adding large caps to a cpu supply helps in this case a bit, especially if you sense the voltage at input of the diode instead of the cpu power caps. Another thing that helps a lot is running at as low speed as possible to keep cpu running longer if you’re not shutting it down and waking up through a watchdog)
Lowering power by halving current/changing to a lower mode: I’d really like a smoother transition. The abrupt lowering can be nasty in some cases when you need to rely on the light. Perhaps some slow ramping instead of a step? Battery voltage is a slowly changing variable anyway and you have no need to respond in a second to a change. Lowering in smaller steps might help on the glitch-issue too (a small change is not as bad to do due to a measuring error eiter). On the other hand an abrupt change might be chosen on purpose to notify the user of battery state.
I wonder if on some batteries 3V limit is too high. At least my Panasonics have a lot of juise below that. At least in sixty545s there is a problem I think. If it detects a low batt and pwm=1 it halves that with a shift, which results in pwm=0 (no mininum level defined like on BLF_VLD-0.4). That effectively turns the light off when it cannot suppy 3.0V level any more. (this may be the indend though?) Perhaps you need two limits: one for lowering power and anoter for permanent switch-off. Especially on moonlight levels this could give one a few hours more running time.
A simple method to add temperature protection would be nice as well. I guess there is no way other than adding a ntc somewhere or changing a mcu for a one with internal sensor (like attiny 25/45/85).
Oh, another thing I’ve been thinking on: I’ll probably add a hidden turbo mode on one of my lamps. It might be something like turn on high, wait for a second (perhaps a blink indicator) and quick turn on/off to get to an overdriven mode. If no temperature monitoring is implemented this could be protected with a timer too that gradually lowers it to high after a couple minutes. A similar interface might be great method to hide rarely used moonlight behind a low mode as well. These would help keep UI lo/mid/high and yet allow relatively easy access to more modes without changing mode groups. I guess I’ll have to code it out and try how it suits my needs. (This might also end up seeming a confusing UI. Making a good one-button UI is no easy task in any case!)
The released codes are great pieces of software. I think one of the major challenges is to put in everything (including the sos everyone seems to hate) and yet keep it configurable, with clean user interface and compact enough. Making the perfect modes for everyone in one file is not an easy task.