Flashlight Firmware Repository

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?

Make sure ā€œmodesā€ array is defined large enough. And you’ll need to mess around with the count_modes function. Reconfigure these lines:

That ā€œ<<3ā€ will need to become ā€œ<<4ā€ and then you’d have to make yourself​ modegroups 16 bytes long instead of 8. This is a bitwise shift, not terribly obvious.

… Or you might take a look at Flintrock’s BistroHD’s count_modes. I think it handles variable-length modegroup sets.

I tried it but I can only get one mode, moon mode.

Perhaps put your code up on pastebin or some other public place so we can take a look?

Here it is https://pastebin.com/ZbTrMaRP
The first modegroup works fine. the 2nd modegroup is a mess and the 3rd modegroup is all moon mode.

All of the mode groups must be 16 values long with the exception of the last one. And I think your modes array needs to be bigger. Give those changes a try and let us know. And update your pastebin when you make changes. Good luck!

Oh ok.
When you said ā€œmake yourself​ modegroups 16 bytes long instead of 8ā€ I thought it’s like this
for(solid_modes=0; (solid_modes < 8) ——change to—-> for(solid_modes=0; (solid_modes < 16) that’s why I changed the 8 to 16 :person_facepalming:
Ok I’ll try your last suggestion. Thanks.

Gotcha. Need to do both.

Now I’m trying to compile biscotti to adopt it to different drivers that I have (moon mode, blinking speeds, etc.) but I keep running into this:

ā€œ$ sh ./build.sh biscotti
avr-gcc -Wall -g -Os -mmcu=attiny13 -c -std=gnu99 -DATTINY=13 -I… -I…/… -I…/…/… -o biscotti.o -c biscotti.c
biscotti.c: In function ā€˜blink’:
biscotti.c:508:9: warning: implicit declaration of function ā€˜_delay_4ms’ [-Wimplicit-function-declaration] _delay_4ms(speed); ^
avr-gcc -Wall -g -Os -mmcu=attiny13 -o biscotti.elf biscotti.o
biscotti.o: In function `blink’:
/home/benoe/Sources/flashlight/biscotti.c:508: undefined reference to `_delay_4ms’
/home/benoe/Sources/flashlight/biscotti.c:510: undefined reference to `_delay_4ms’
/home/benoe/Sources/flashlight/biscotti.c:511: undefined reference to `_delay_4ms’
biscotti.o: In function `toggle’:
/home/benoe/Sources/flashlight/biscotti.c:561: undefined reference to `_delay_4ms’
/home/benoe/Sources/flashlight/biscotti.c:561: undefined reference to `_delay_4ms’
biscotti.o:/home/benoe/Sources/flashlight/biscotti.c:561: more undefined references to `_delay_4ms’ follow
collect2: error: ld returned 1 exit statusā€

I didn’t clone the whole repository but handpicked the files, but everything should be in place.

Any of you guys have ā€œHello Worldā€ equivalent code for flashlights, like simplest code there is!
Something with just one ā€œregularā€ mode maybe one blinky mode (so I could see how loops work) and that’s it.
I am really trying to understand ramping firmware by TK but I am just not making any progress with my modifications :frowning:

One of the smallest is DrJones’ MiniDrv. From the looks of it, it is on-time memory, no blinky modes so no loops.

There are also several STAR variants that might be a good place for an intro to looping, etc. Here’s one from JohnnyC. TK also has some STARs worth checking out.

Tried all your suggestions and now it is working flawlessly. :+1: Thanks for your help.

Awesome! And you’re welcome. :beer:

It’s probably missing a define somewhere, or has an old version of tk-delay.h. The _delay_4ms() thing was added fairly recently to save space and make room for extra safety checks. IIRC I still haven’t merged it into trunk yet because I changed some stuff which would require changes in other projects. Maybe now would be a good time to do that.

It needs this in the .c file:
#define USE_DELAY_4MS

… and it needs the version of tk-delay.h which includes the 4ms stuff. It’s currently in the sandbox branch and the convoy branch, but not yet in trunk.

Which ramping firmware? What do you want to change? I might be able to point out where to start.

Thanks TK, first for making all this nice firmwares and then for helping us implement them :slight_smile:

So, in Crescendo, after double-tap it will ramp down to poweroff() and then ramp up again,
I thought it would be interesting to stop it after it ramps down but at some minimal output (5) not at powered off led, so you would know that the switch is in on position.
I commented out this (line 684)

this coused it to power off after ramp down (didnt go up again).
Then I tried adding this:

so, if ramping direction is –1 (we are ramping down) then proceed with ramping until mode_idx is higher than 8, when mode_idx is equal to 8 then it should stop ramping down and jump to set_output (5), (also tried set_mode(mode_idx); because mode_idx should at that point be 8 which is output level 5)… bit it alway goes all the way to 0 output (if it were to stop at 5 then you could do short tap to start ramping up again).
I also had one iteration where it went all the way to 0 output and then activated set_output(5) stopping it at level 5 which is kinda ok but I wanted it to stop before it hits 0, that would be correct way.