Flashlight Firmware Repository

HQ, I might not understand details of crescendo enough to understand some context I'm missing here.

I can answer a lot for bistro though, and what I've done to it. Classic Bistro doesn't use any timer or idle state for sleep modes. Well it does have waits that are done just by a tight do-nothing loop at full mcu power, so that's the cpu clock timer, but a not a "timer".

I've measured that at about 4mA current draw. The ADC adds about 0.15mA (150uA) so not much. I added idle sleeps, using the clock timer. that reduced it to about 2.1mA, which was important in the context of OTSM.

I also added power off sleep powered by capacitors, using the watchdog timer. This is for fully powered off clicks though, to time the clicks. You can't go to deep sleep while the light is on because PWM won't work.

The watchdog isn't that useful when the light is on because the fastest it will go is 16ms, and to program strobes you need faster than that anyway. So if you want a sleep mode for standard loops, you're going to need one that uses idle sleeps and the clock anyway, and at that point you've already got that, so why use the watchdog?

This idle sleep does increase moon mode battery life significantly (I'd guess about 50 to 70% for 1lumen, could be more if really designing just for that), but that's not why I added it. I added it because it takes 4ms to detect power off and that eats up a bunch of my cap power before I can get the mcu to full sleep, so I need full power to also be as low as possible.

Now the full sleeps that are watchdog timed are down around 8uA, but that requires BODS to get that low (and the right chips), otherwise you'll be up around 30uAs. But again, no PWM during those.

If you're intereste, it's here:

https://budgetlightforum.com/t/-/44344

The idle sleep timer is setup in fr-delay.h.

Can someone help me with latest biscotti?

I would like to flash it but don’t understand all that code.

I would like small change.
On mode 1 have 0.1%, 1, 10, 35, 100, battcheck (no strobe and biking) if possible.

Can someone give me .hex file so I can just flash it without much trouble?

To change that, replace this…

PROGMEM const uint8_t modegroups[] = {
     1,  2,  3,  5,  7,  POLICE_STROBE, BIKING_STROBE, BATTCHECK,

… with this:

PROGMEM const uint8_t modegroups[] = {
     1,  2,  3,  5,  7,  BATTCHECK, 0, 0,

However, there are some other things which depend on the specific driver you’re using. I can’t provide a universal .hex file which works on all drivers. Specifically, the voltage calibration and moon level are pretty sensitive to different hardware. What driver are you using?

Ok, here is a quick & dirty compile with that change. Double check the LVP/battcheck, though. It can vary from driver to driver.

EDIT: oops, TK beat me to the important stuff. What she said :wink:

I’m using red “convoy” branded driver from Simon with 8x7135.
Sorry I didn’t mention it.

Side note about flashing firmware on that driver: incase you haven’t heard about the need to cut the grounding trace on pin5, check out this page over on the flashing guide

I have seen it and already did.

I’m good with hardware part, but code got me lost :blush:

I try to flash driver but got error and not working driver as result. :cry:

Also tryed to flash original fw I saved from driver but same error.

Error

What I flash

What I read

Thanks Flintrock for this answer that helped me at several points. Although I’m looking for 13A firmware. Bistro and your HD is way above my head. I looked at HD briefly, too much code I don’t yet understand and it takes me way too long to google every unknown part.

I just compiled (all with -Os) my old fashioned, ‘Star’-based firmware with LVP to 950 bytes. Then I deleted the flash before stepdown and got 826 bytes. Wow. That alone eats a lot of space.
Then I changed the rest of the LVP part to the code from biscotti (not WDT based) and compiled to 722 bytes.

Now I understand how TK could cram so much into the 13A…

But as I understand that Sleep-Mode-Idle and WDT really saves some mA, and I don’t need strobes, I will try to keep WDT unless all I want to add exceeds 1k.

Hmmm, you firmware people really have been busy in the last 2 years…
Thanks for sharing, to all of you.

Sure, yeah WTD should be fine for idle if you don't need strobes. For sleep mode idle you don't need to see all that code, just the fr-delay.h, but I doubt you need to see it. You know how to use WTD and how to enter sleep.

Bistro HD actually has attiny13 support. In fact it has a biscotti-HD configuration already built in the Makefile, (and somewhat customizable from its config file) that comes in a few bytes smaller than original biscotti with a couple of added features. I don't recall if I have the sleep mode enabled. It's the OTSM_powersave option, which actually works even if OTSM is not used (I should change the name of that control).

It does seem that I've put a warning and an undefine for this option in attiny13. But now I can't remember or see any good reason why. I just uncommented that and compiled it with that option and it compiled fine, so it must not be using anything undefined for attiny13. maybe I just did it to save bytes. Hmm.. It does bring the biscotti build up to 1032 bytes, but if nothing else just removing the added turbo-timeout feature will get it back down. I really can't see why I disabled that option now. Maybe I'll un-disable it. hmm..

The bistro HD code does start to look a bit overwelming. I tried to avoid code re-organization becuase there was a tradition of single file compilation without even function prototypes. This makes it easier for some simple compiling methods and was fine for bistro, but it starts to get close to its limit now, and is bending the rules a bit.

Anyway, one thing I did add is the makefile produces preprocessor output for all builds, stripped of comments. Other than some ugly MACRO expansions of things like PORTB and pgm_read_bytes(), these put the code into the lean and clean form after all preprocessor configurations are factored in. Maybe I'll start including those in the distribution.

So my single-cell battery charger had been way under charging recently and I hadn't noticed or cared much. But that explains this light not getting hot. (I thought I had others I'd been using before that got hotter). Now it runs at 3.5A (on still slightly less than full Pannies) and the thermal protection kicks in. But it is very on and off. It hits the limit and marches way down to 1st mode... cools off a while, and marches straight back up, repeats. Probably related to poor thermal path.

The thing is though really nailing feedback problems like this in a general way, is very very difficult. You can do it with just a proportional gain (probably what Dr.Jones does), but there's probably no one gain that will work well for every light. You'd probably need to work out a response time and extrapolate curves to predicted temperatures, correct, re-measure, extrapolate the correction... Not easy, especially for an attiny.

I wonder though if just having it somewhere inbetween bistro and BLFA6 would be good.

Update: ok, so the problem is that the goal isn't even clearly defined. There are really two very separate uses. One is someone wants to be able to see something with the most light possible once in awhile. That's true turbo mode. Two is someone wants to get the maximum sustainable power out of the light, possibly in changing conditions (this is biking mode really) For option one, finding the stable power level isn't even useful, going to that level prevents ever returning to turbo because you keep the light maximally hot. And dropping down way low, and automatically returning to turbo also isn't useful. You're not going to be able to know when the user needs turbo again anyway, and bouncing up and down is silly. So timeout, or temp-out and bump up makes tons of sense for option 1. Dynamic regulation doesn't make sense for option 1. For option 2 you never need to even reach turbo. The best system would analyze the heat curve and zoom in on the sustainable target without ever overshooting it in the first place. You could overshoot a little and then settle in, but I don't see much point. These might even be ideally different modes, although every mode should probably have the temp regulation applied, for safety.

Option 1 can be modified so it "times"-out on temperature instead of time. That would be nice, but it's still then just a single big step down and wait for the user to bump it up.

The further problem though is that option 2 is very very difficult to actually achieve in a general way for every light you might flash the firmware to. Gain feedback probably needs to be tuned, or needs to be very smart. So is it even sensible to have any mode that dynamically regulates on a generic firmware? Maybe it makes sense just to have a defined COOLDOWN mode and any time any mode maxes out on temperature it resets to there, with ability for bump up (but this time with timeout?). That adds safety to all mode levels, and provides option1 functionality, but doesn't attempt to provide option 2, and certainly doesn't attempt to mix them, which I think just doesn't make sense really.

Ok, nuff talking stuff done.

attiny13 idle

Regarding powersaving in attiny13 I had disabled the attiny idle sleep aparently because it didn't compile on the 13 and it just got it going, but the reason was that Atmel decided to do entertaining things like call the timer 0 interrupt TIM0_OVF_vect on attin13 and TIMER0_OFV_vect on attiny25, just to mess with us. So some macro defines sorted it. So biscotti-HD for attiny13 can now have pwersaving and actually it does fit (confused myself earlier). I consider that one of several customizable bonus features though.

Thermal turbo boost

Regarding thermal control. I threw together a quick BLFA6 like turbo except it applies to all modes and it jumps down based on temperature not time. Otherwise it's like BLFA6 though, not like bistro. When too hot, it jumps down to a predefined mode (default RAMP_SIZE/2 for now). A fast tap bumps it back up. I thought it might be nice to switch to timeout control after the bump-up but that probably adds more code, and actually I like it this way. You still get 4 seconds minimum because that's how long it spends verify the overtemp, but then it will pull you back down again if it's still too hot. 4s is enough to see something in a pinch. I could somehow pad it with initial time to increase minimum time without further increasing the first overheat delay. I really like this setup. The auto multi-step down auto multi-step up alternative just starts doing its own dance that doesn't really help me use the light. This just protects the light, and then puts me back in control. Oh and it came in 10 bytes lighter.

I'd consider a true temp regulated mode as a different thing and a more difficult task, and something to be added in addition to this. I might play with it. I think you can roughly predict the final temp as linear combination of the last two readings. It doesn't need to be a good prediction so long as it converges correctly. The tough part is figuring out the correction gain. This is predictive though not reactive, and so hopefully wont oscillate, but it still probably can oscillate in some conditions. Anything mathish like this though tends to take a bunch of bytes.

Hey FR, I’d love to take a peek at that attiny13a interrupt code. Do you have it posted anywhere?

It's in HD:

https://budgetlightforum.com/t/-/44344

Nothing actually changed in the code, just some of ATMEL's register macros. As I recall TIMER0_OVF_vect had to change to TIM0_OVF_vect and TIMSK and to change to TIMSK0. there might ahve been another one but it will be obviouus when you try it.

So I change them to _TIMER0_OVF_VECT_ and _TIMSK_ and in fr-tk-attiny.h

add

#if ATTINY == 13

#define _TIMSK_ TIMSK0

...

you get the point.

I'll post this new version up soon though, but that's all I change, oh and removing the override on that on option.

Oh yeah, the relevant part of the code is in fr-delay.h. You need the interrupt there, and the initialization is mostly done in the delay function, although as I recall actually configuring and enabling timer0 is done in init_mcu in bistro.c You can ignore the PWM4 stuff. Basically if PWM4 is engaged I have another interrupt waking at known intervals anyway, so I use that instead and don't setup another one, but you can just ignore that.

I've made a post for the thermal control discussion (if any) here:

This is the sort of thing a nicer MCU would really help with. However, given the attiny25 as a target platform, getting it to work is … unpleasant.

The standard method is PID, which is far fancier than what bistro does. Kalman filters might be an even better method, or a complementary method. I doubt there’s enough room to do either of those properly though, so I was thinking of upgrading to 10-bit sampling and doing something with the first or maybe even second derivative of the temperature readings. That way, it could react based on whether the temperature is rising or falling, or even if it’s accelerating, instead of just whether it’s currently too hot or not.

A first derivative would be pretty simple (even on attiny)… just subtract the previous measurement from the current measurement. Then add, say, two or four times that to the current temperature to predict where it might go in the near future. If the prediction is too hot, ramp down. If the prediction is too cold, ramp back up. Both adjustments can be proportional to how much the value deviates from the target.

This method would amplify any noise in the measurements though, so depending on how noisy the measurements are, a lowpass filter might be required.

TK, I'm not sure you need second derivative. You have the benefit of knowing that at least if the mode hasn't changed recently, heat tends to move exponentially toward an asymptotic limit, with a fixed relationship between first and second derivative. That means the end point is related to the sum of the preent value and something times the slope. The second derivative helps if there have been recent mode changes and there may be an overshoot hump coming, you could detect that. Yeah, that could help avoid oscillations, as you point out though, if you have the resolution for this kind of correction and the computing power. Notice if you do this well, predictively, you probably never reach turbo.

Oh, also the thermal delays can be large enough that you may already have two unavoidable humps queued up in the heat profile. Hard to predict that. But if you're doing things well from the start, maybe you don't ever have any humps, which is why I think first derivative might get close enough. I think the hard part is knowing the delay well. If you're reading recent changes and assuming you need to adjust but those changes are related to what happened 20 seconds ago, your adjustments are wrong and you're creating oscillations.

The hardest thing about all this is the timescales for the delay are similar to the time scale for the full range change. That spells trouble. Of course we know the reason, the sensor is in the wrong place.

Finally I will have time to play with the code.
I already started today.
Accomplished nothing.
C language is hard…

In bistro firmware, how do I add more modes? I can only get maximum of 9 modes including moon mode. I want 12 modes, should I add more numbers here?