STAR Firmware by JonnyC - Source Code and Explanation

1335 posts / 0 new
Last post
Tom E
Tom E's picture
Offline
Last seen: 4 hours 21 min ago
Joined: 08/19/2012 - 08:23
Posts: 14199
Location: LI NY

Sorry, it's a little off topic bout the Tiny13A issues I'm having, but here's more info for those interested:

  So far, all my problems seem to be from parts bought in one order here:

http://www.ebay.com/itm/5PCS-MCU-IC-ATMEL-SOP-8N-ATTINY13A-SSU-TINY13A-SSU-ATTINY13A-/250936543547?ssPageName=ADME:L:OC:US:3160

At the time, he sold in batch's of qty 10, so I bought 2 batch's for a total of $13 shipped (qty 20 total) back on June 23rd. This evening, I want to go back thru these pieces and see if any will program, and verify that all my non-working boards did come from that batch. I'm thinking this makes a lot of sense.

Anyone know if it's possible that legit Tiny13A's may not be programmable (locked) when purchased? They sure look legit and not counterfeit, but maybe there is a version that can't be programmed via the standard SOIC-8 method?

wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

Tom E wrote:
[snip]

Anyone know if it’s possible that legit Tiny13A’s may not be programmable (locked) when purchased? They sure look legit and not counterfeit, but maybe there is a version that can’t be programmed via the standard SOIC-8 method?

Yes, it’s possible. If certain fuse bits are set during programming this can happen. At that point only “high voltage” programming can be used, the ISP type we normally use will not work. In this thread in posts #52-61 we discuss the issue a little and I link to a “rescue programmer” project.

I don’t know if it’s done at Atmel or elsewhere, but I’m told that pre-programmed AVRs can be purchased. They’d be reeled and everything, ready for pick-and-place. Maybe what you received are excess pre-programmed ones with the situation I described above?

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

RMM
RMM's picture
Offline
Last seen: 1 year 3 months ago
Joined: 07/23/2013 - 13:47
Posts: 4006
Location: USA

Tom E wrote:

Sorry, it's a little off topic bout the Tiny13A issues I'm having, but here's more info for those interested:

  So far, all my problems seem to be from parts bought in one order here:

http://www.ebay.com/itm/5PCS-MCU-IC-ATMEL-SOP-8N-ATTINY13A-SSU-TINY13A-SSU-ATTINY13A-/250936543547?ssPageName=ADME:L:OC:US:3160

At the time, he sold in batch's of qty 10, so I bought 2 batch's for a total of $13 shipped (qty 20 total) back on June 23rd. This evening, I want to go back thru these pieces and see if any will program, and verify that all my non-working boards did come from that batch. I'm thinking this makes a lot of sense.

Anyone know if it's possible that legit Tiny13A's may not be programmable (locked) when purchased? They sure look legit and not counterfeit, but maybe there is a version that can't be programmed via the standard SOIC-8 method?

Just a thought:  use an old (clean) toothbrush and some rubbing alcohol and scrub the pins well.  You can flash while still wet. Sometimes I can't get chips to program that must have flux and/or oxide buildup and this works miracles.  

Mountain Electronics : batteries, Noctigon, and much more! What's new? 

Tom E
Tom E's picture
Offline
Last seen: 4 hours 21 min ago
Joined: 08/19/2012 - 08:23
Posts: 14199
Location: LI NY

Ok, but I did continuity tests on all 6 pins clipped from the chip to the USB dongle and it worked. I posted the question to the vendor about not being able to program them, and asked if they were possibly pre-programmed.

I'm going to put in an order for a bunch  of Tiny13A's with DigiKey this weekend - need time to figure all the parts I'll be needing - might as well be sure I'm stocked up. Might order another good clip just to have a good spare.

Thanks wight for that thread tip - read it, interesting...

wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

JonnyC wrote:

HighEfficiency wrote:
[snip]

 

When I get a chance I need to look at my code again. I built a custom one for police lights I was doing, and it functioned just as you describe. It also had the option to gradually ramp down over x number of seconds, instead of step down on the timeout. I thought I put that in the main program as a compile option, but if not I’ll add it.

You didn’t include it as a compile time option as far as I know, but you did include full instructions in your thread over here: First use of lathe – P60 pill for L2T – the instructions are spread across several posts in that (short) thread.

Everything is there, I know because I built a dropin with that code in the past week. I mentioned it in the OP here. It functioned just like you described, although I have not had time yet to properly sink the P60 and the OG XM-L I used starts at 9A so I’ve only run it for a few sec at a time and verified that it functions. I set mine up as medium and turbo w/ rampdown and that’s it.

Beginners may need a hand, but they might not. There are really very few code changes required! I’ve been thinking that as a room clearing light I’d like to add a 15s+ of solid turbo before the smooth rampdown. Should be straightforward to add, but that dropin is already together and unlikely to be rebuilt. I like the concept, so I’m sure I’ll have another chance to make that change and post the code.

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

Tom E wrote:

Thanks wight for that thread tip – read it, interesting…

You’re welcome. HV doesn’t have to be for rescue, nicer programmers can actually load a program using HV programming. I think you’re looking at a $30-60 programmer to get that feature though? I guess it still might be worthwhile in the very long term if you can save $0.30/ea or so per ATtiny13A… after about 100-200 chips you break even? Of course that’s assuming that these aren’t total fakes! They could be mislabeled/etc.

What error text does AVRDUDE give you?

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

HighEfficiency
HighEfficiency's picture
Offline
Last seen: 3 years 10 months ago
Joined: 02/05/2014 - 11:33
Posts: 74
Location: USA

[/quote]

 

When I get a chance I need to look at my code again. I built a custom one for police lights I was doing, and it functioned just as you describe. It also had the option to gradually ramp down over x number of seconds, instead of step down on the timeout. I thought I put that in the main program as a compile option, but if not I’ll add it.

[/quote]

I for one would be very interested in the smooth ramp down. Thanks again for all the help. Wish I had something more to contribute developmentally.

Tom E
Tom E's picture
Offline
Last seen: 4 hours 21 min ago
Joined: 08/19/2012 - 08:23
Posts: 14199
Location: LI NY

I'll gladly eat the $13 spent on the bad parts rather than investing into the tool - agreed Smile. Thought the AVRDUDE error msg was the same as when it's mounted wrong or missing - not sure, @work now... DigiKey all the way now... Actually, I bought Tiny13A's from BangGood originally and they worked out well, even though they were individually wrapped - weird.

JonnyC
JonnyC's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 01/14/2011 - 19:12
Posts: 1148
Location: Green Bay, WI - USA

wight wrote:
JonnyC wrote:

HighEfficiency wrote:
[snip]

 

When I get a chance I need to look at my code again. I built a custom one for police lights I was doing, and it functioned just as you describe. It also had the option to gradually ramp down over x number of seconds, instead of step down on the timeout. I thought I put that in the main program as a compile option, but if not I'll add it.

You didn't include it as a compile time option as far as I know, but you did include full instructions in your thread over here: "First use of lathe - P60 pill for L2T":http://budgetlightforum.com/node/32550 - the instructions are spread across several posts in that (short) thread. Everything is there, I know because I built a dropin with that code in the past week. I mentioned it in the OP here. It functioned just like you described, although I have not had time yet to properly sink the P60 and the OG XM-L I used starts at 9A so I've only run it for a few sec at a time and verified that it functions. I set mine up as medium and turbo w/ rampdown and that's it. Beginners may need a hand, but they might not. There are really very few code changes required! I've been thinking that as a room clearing light I'd like to add a 15s+ of solid turbo before the smooth rampdown. Should be straightforward to add, but that dropin is already together and unlikely to be rebuilt. I like the concept, so I'm sure I'll have another chance to make that change and post the code.

Wow, you know my posts better than I do!  I still haven't done *%# with those builds.  And wow, that looks like a great driver you built.  I haven't even dabbled into the FET arena, I simply cannot keep up with all of the posts on the subject!  If I ever want something other than a NAJNG, I'll just order it pre-built from Richard Smile

I'll work on getting the "immediate turbo ramp" feature in the main code hopefully today.  Then I need to start the port to the ATtiny25.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

Speaking of FETs, I wasn’t happy with the moon level on mine… so I added a feature to let me fine-tune the output of moon. Using fast PWM=0 I was getting like 0.05 lm. But fast PWM=1 gave me about 11 lm. And phase-correct PWM=1 gave me like 6 lm or so. I wanted something closer to 0.3 lm.

So, I added PFM to moon mode, and only to moon mode. This means, instead of doing fast PWM=0/255, I can adjust the brightness gradually. I settled on 0/40 for this particular light, where a lower denominator makes the output brighter. I might go further, to 0/30, for an even brighter moon.

An example is here:

http://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/view/he...

This also means that moon mode pulses a lot faster. In the case of 0/40, it pulses at about 120 kHz.

I should mention that the output is still highly voltage-sensitive, especially on PWM=0, so it will still get extremely dim as the cell gets low. The battery and FET just can’t get up to full power in the ten-millionth of a second the pulse lasts, and that’s especially true when the cell isn’t full. The highest mode may drop to half its original output on a low cell, but moon will drop pretty much all the way to zero.

But at least moon is a nice comfy level for the first half of each charge cycle. Smile

wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

ToyKeeper wrote:
Speaking of FETs, I wasn’t happy with the moon level on mine… so I added a feature to let me fine-tune the output of moon. Using fast PWM=0 I was getting like 0.05 lm. But fast PWM=1 gave me about 11 lm. And phase-correct PWM=1 gave me like 6 lm or so. I wanted something closer to 0.3 lm.

So, I added PFM to moon mode, and only to moon mode. This means, instead of doing fast PWM=0/255, I can adjust the brightness gradually. I settled on 0/40 for this particular light, where a lower denominator makes the output brighter. I might go further, to 0/30, for an even brighter moon.

An example is here:

http://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/view/he...

This also means that moon mode pulses a lot faster. In the case of 0/40, it pulses at about 120 kHz.

I should mention that the output is still highly voltage-sensitive, especially on PWM=0, so it will still get extremely dim as the cell gets low. The battery and FET just can’t get up to full power in the ten-millionth of a second the pulse lasts, and that’s especially true when the cell isn’t full. The highest mode may drop to half its original output on a low cell, but moon will drop pretty much all the way to zero.

But at least moon is a nice comfy level for the first half of each charge cycle. Smile


That aspect just doesn’t sit well with me. (A mode which potentially does not generate light.)

If I was working on low moonlight + high turbo I think I’d try to bring the voltage monitoring into the picture. In other words I’d scale my moonlight PFM freq down as battery voltage dropped. Even doing it very linearly seems better than not doing it at all. At least it would light up with a partially discharged cell! Am I missing something important?

Interesting stuff with the PFM. I don’t really understand the mechanism, there’s a lot to parse just staring at the few lines you use in the code vs the plethora of info in the datasheet. I do understand what’s happening though, thanks to your relatively clear code & comments (both here and in the code). I guess You’re making use of “TOP?

I can rarely make heads or tails of registers. I suck at number system conversions, addresses, and notation. I can plug 0×08 into a HEX>BINARY converter and get 0000 0000 0000 1000, and I take it that the 4th bit (bit 3) has been set to 1. Actually pairing that up with the stuff from the datasheet…. I assume I should be looking at page 73, but again – I can’t understand the notation. The struck text is true, but I think I’ve got it now. I was missing that both bit 3 and bit 0 got set. So we are in “Mode 5” where we update OCRB at TOP and TOP is OCRA (all using Phase Correct). I know it’s pitiful, but I feel accomplished having finally gotten that worked out.

Thanks for doing the heavy lifting on this, it seems like a good advancement to me!

EDIT: For others trying to get a handle on this, I referred to sections 11.2.2 of the ATtiny13A datasheet (on page 60) as well as the chart at the top of page 73 and the little control register diagram in the middle of that page (so the top of section 11.9.2).

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

JonnyC
JonnyC's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 01/14/2011 - 19:12
Posts: 1148
Location: Green Bay, WI - USA

I added the gradual turbo ramp down as a compile time option (TURBO_RAMP_DOWN) to both STAR and STAR_off_time.

https://github.com/JCapSolutions/blf-firmware

Instead of having a predefined mode to step down to, you define a MODE_TURBO_LOW PWM level.  You can still have it the same as MODE_HIGH if you'd like, or just skip the high mode altogether.  I got rid of the whole MODE_HIGH_W_TURBO thing while I was at it.  Because the WDT was set to 500 ms previously, and because the turbo ramps down only 1 PWM level per "tick" (WDT timeout), going from 255 to 140 would take almost a minute.  Instead of stepping down by 1 output level you could step down by 2.  But I added another compile time option of TICKS_250MS, which will change the WDT ticks to 250 ms, so the turbo ramp down described above will take 30 seconds.  Obviously tweak it however you want, but also realize that the "tick" timing affects the mode storage in the STAR program.

This addition was not applied to STAR_momentary and STAR_dual_switch.  I would need to devote some time to making and testing the changes, so it might be a while until I get around to that (maybe when I actually get around to building a light with those UI's, because I've never used them).

EDIT:  And please, as always, if you notice any bugs while attempting to use these let me know!

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

wight wrote:
That aspect just doesn’t sit well with me. (A mode which potentially does not generate light.)

If I was working on low moonlight + high turbo I think I’d try to bring the voltage monitoring into the picture. In other words I’d scale my moonlight PFM freq down as battery voltage dropped.

I’m not terribly happy about it either, but my choices were either voltage-sensitive moon or no moon at all. I did end up bumping up the level a bit though (0/30), so it now ramps from about 3.3 lumens at 4.22V down to somewhere around 0.05 lumens at 3.6V (will have to measure that when I get my battery drained though).

In-between, it spends most of its time in the 0.2 lm to 1.5 lm range, as far as I can tell, which will have to be good enough for now. But I did at least omit moon mode from the low-voltage step-down, since at that point it’s basically the same as “off”.

I considered making it change based on voltage, but the curves are rather non-linear, doing the math on the MCU consumes a lot of space, a table would also consume a lot of space, and it’s not even terribly effective near the bottom end of the voltage range… it still gets extremely dim even with the ceiling set just barely above the floor.

Maybe I could use a small table if I free up some bytes elsewhere, but I’m not sure it matters to me that much.

wight wrote:
Interesting stuff with the PFM. … You’re making use of “TOP? … So we are in “Mode 5” where we update OCRB at TOP and TOP is OCRA (all using Phase Correct).

Yes, I’m using the TOP mechanism. I called it a ceiling. However, I’m not using phase-correct PWM here, it’s fast PWM. The “TOP” thing works in either mode, but phase-correct turns off entirely with PWM=0 and at 1 it’s too bright. I agree that the documentation is particularly convoluted about all this.

FWIW, the cypreus.c firmware got updated quite a bit today. Also, my Ferrero_Rocher/Ramping_UI_table.c firmware makes use of PFM for smoother ramping on the lowest modes, if you’re curious to see another use of PFM.

It’s an interesting concept, but it seems to have very limited usefulness in a flashlight driver.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

JonnyC wrote:
I added the gradual turbo ramp down as a compile time option (TURBO_RAMP_DOWN) to both STAR and STAR_off_time.

Because the WDT was set to 500 ms previously, and because the turbo ramps down only 1 PWM level per “tick” (WDT timeout), going from 255 to 140 would take almost a minute.  Instead of stepping down by 1 output level you could step down by 2.  But I added another compile time option of TICKS_250MS, which will change the WDT ticks to 250 ms, so the turbo ramp down described above will take 30 seconds.  Obviously tweak it however you want, but also realize that the “tick” timing affects the mode storage in the STAR program.

Awesome, imperceptibly smooth turbo step-down. Smile

Instead of making the ‘tick’ faster, you could also do something like this:

if ((turbo_ticks > TURBO_LENGTH) && (PWM_LVL > TURBO_STEPDOWN)) {
    PWM_LVL = PWM_LVL - (PWM_LVL >> 5);
}

This way, each step is roughly 3% (small enough to be unnoticeable), and it goes from 255 to 120 in 27 steps (or 13.5 seconds). Should work fine as long as it doesn’t need to drop below PWM=32.

BTW, I discovered today that the WDT is pretty much irrelevant for off-time firmware unless you want to save a tiny amount of power. So, it helps the moon mode run longer but otherwise the power difference is pretty negligible. So, I removed WDT entirely to make room for other code.

Instead I added a non-WDT turbo step-down to my off-time firmware (cypreus.c). It’s not a smooth step-down like yours, but since it’s running on an extremely overdriven host I made it a 2-level step-down. In this case, it’ll drop from ~3000 lumens to ~1400 lumens after 30 seconds, then drop down again to ~500 lumens after another 30 seconds. I should probably make it less than 30 seconds, but that’s what it’s set to now. Hopefully that’s at least enough to keep it from catching on fire.

It’s here if you’re curious:
http://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/view/he...

HarleyQuin
HarleyQuin's picture
Offline
Last seen: 6 months 2 weeks ago
Joined: 03/29/2013 - 04:47
Posts: 588

Dual Mode Change with Single Reverse Clicky

Realized by vex_zg, who thankfully provided the code he used.
Much obliged!

I just want to narrow it down here to the changes he made, to make it easier for anyone who might be interested as well.

What does it do: A short press with the reverse clicky increases the mode, a slightly longer press decreases the mode. It’s like best of both worlds.
Result: Works like a charm.
Verdict: It’s priceless.

I extracted the lines that vex_zg had used and transferred them into a stock StarOfftime1.3. After tweaking the thresholds I get reliable results with short-press and long-press (Toykeeper has even implemented 3 timeframes).
I prefer thresholds 150/100 for now, these make for roughly guesstimated 0-0.5 sec for a short-press and 0.5-1.5 sec for a long-press.

This is with a usual 1yF off-time-cap, no higher capacity required.

So here are the changes.
If the formatting looks odd to you programming aces: I altered it to get a grasp of what this code means, to follow its logic. So it may not be by the book. I don’t know the book. :bigsmile:

*************************************************************************

1.
Two thresholds instead of single CAP_THRESHOLD

 
#define CAP_THRESHOLD_SHORT    140
#define CAP_THRESHOLD_LONG    112

2.
Mode change without wrap around. Not necessary for dual mode change, but a nice addition.
inline void next_mode() 
	{
	if	(mode_idx  0 && mode_dir  -1) { mode_idx = 0; }		 
	else	{ mode_idx += mode_dir; 
			if (mode_idx > (mode_cnt - 1)) { mode_idx=mode_cnt-1; }			
			}			
	}

3.
Comparing ADCH with the capacitor thresholds. The first and last lines are similar as in OffTime1.3, so it’s easily implemented.
if (ADCH > CAP_THRESHOLD_SHORT) 
		{
		next_mode(); 
		store_mode_idx(mode_idx);
		}
else	
		{
		if (ADCH > CAP_THRESHOLD_LONG) 
		{
		mode_dir=mode_dir*(-1);
		next_mode(); 
		mode_dir=mode_dir*(-1);
		store_mode_idx(mode_idx);
		}		 
		else	{
				#ifndef MEMORY
				mode_idx = ((mode_dir == 1) ? 0 : (mode_cnt - 1));
				store_mode_idx(mode_idx);
				#endif
				}				
		}

Again kudos to vex_zg for sharing it.
Have fun.

Oshpark Boards:
HQ ProgKey: Universal Driver Programming Key . Boost: HQ 15mm/17mm programmable boost driver with ATtiny13A
46mm Triple-Channel: BLF SRK FET v3 . 17mm Linear: HQ10D / HQ4D / HQ4S . Contact Boards: 22/24/26mm

wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

ToyKeeper wrote:
wight wrote:
That aspect just doesn’t sit well with me. (A mode which potentially does not generate light.)

If I was working on low moonlight + high turbo I think I’d try to bring the voltage monitoring into the picture. In other words I’d scale my moonlight PFM freq down as battery voltage dropped.

I’m not terribly happy about it either, but my choices were either voltage-sensitive moon or no moon at all. I did end up bumping up the level a bit though (0/30), so it now ramps from about 3.3 lumens at 4.22V down to somewhere around 0.05 lumens at 3.6V (will have to measure that when I get my battery drained though).

In-between, it spends most of its time in the 0.2 lm to 1.5 lm range, as far as I can tell, which will have to be good enough for now. But I did at least omit moon mode from the low-voltage step-down, since at that point it’s basically the same as “off”.

I considered making it change based on voltage, but the curves are rather non-linear, doing the math on the MCU consumes a lot of space, a table would also consume a lot of space, and it’s not even terribly effective near the bottom end of the voltage range… it still gets extremely dim even with the ceiling set just barely above the floor.

Maybe I could use a small table if I free up some bytes elsewhere, but I’m not sure it matters to me that much.

wight wrote:
Interesting stuff with the PFM. … You’re making use of “TOP? … So we are in “Mode 5” where we update OCRB at TOP and TOP is OCRA (all using Phase Correct).

Yes, I’m using the TOP mechanism. I called it a ceiling. However, I’m not using phase-correct PWM here, it’s fast PWM. The “TOP” thing works in either mode, but phase-correct turns off entirely with PWM=0 and at 1 it’s too bright. I agree that the documentation is particularly convoluted about all this.

FWIW, the cypreus.c firmware got updated quite a bit today. Also, my Ferrero_Rocher/Ramping_UI_table.c firmware makes use of PFM for smoother ramping on the lowest modes, if you’re curious to see another use of PFM.

It’s an interesting concept, but it seems to have very limited usefulness in a flashlight driver.

Yeah, fresh eyes this morning show that I had another crazy interpretation of things. At least I started to put my finger on something I guess… OK, combing through I think I see where WGM00 gets set, that’s when we do TCCR0A=0×21. What I don’t see is where WGM01 gets set. OK, line 453: TCCR0A = FASTPWM; So we are actually in Mode 7, not Mode 5 as I said earlier. WGM00, WGM01, and WGM02 are all set while in Moon mode. In other flashlight modes we are in waveform generation Mode 5 due to setting TCCR0A=0×21. Is that correct?
Changing the subject a little, I think JonnyC wrote this code with a hex value because people could easily increase it by incrementing like a decimal number:
    TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)

As far as I know the Waveform Generation Mode isn’t going to work that way. Can we change this:

    TCCR0B = 0×08 | 0×01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64…)
To read like this instead:
    TCCR0B = (1 << WGM02) | 0×01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64…)

I think that using the register names instead of hex [wherever reasonably feasible] would make the code a tiny bit more accessible. ?

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

HarleyQuin wrote:
Dual Mode Change with Single Reverse Clicky

Realized by vex_zg, “who thankfully provided the code…

I extracted the lines that vex_zg had used and transferred them into a stock StarOfftime1.3. After tweaking the thresholds I get reliable results with short-press and long-press (Toykeeper has even implemented 3 timeframes).
I prefer thresholds 150/100 for now, these make for roughly guesstimated 0-0.5 sec for a short-press and 0.5-1.5 sec for a long-press.

Again kudos to vex_zg for sharing it.
Have fun.


You know, I never got around to looking at vex_zg’s code. Oops. It looks like we wrote almost exactly the same code though. Both offer 3 time frames — short, medium, long. The default STAR off-time uses only two timeframes — short and long.

I still want to tweak the thresholds more… sometimes I have trouble getting a medium press. Otherwise though, it seems to work pretty well. If JonnyC finds it worthwhile he might include it in the default STAR firmware. However, it does complicate the UI and STAR generally tries to “keep it simple, stupid” so it might remain a custom patch.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

wight wrote:
OK, line 453: TCCR0A = FASTPWM; So we are actually in Mode 7, not Mode 5 as I said earlier. WGM00, WGM01, and WGM02 are all set while in Moon mode. In other flashlight modes we are in waveform generation Mode 5 due to setting TCCR0A=0×21. Is that correct?

Yes, I think so. I wanted the blinky modes to actually turn off between blinks, so I made it use phase-correct PWM by default (and only use fast PWM for the always-on modes).

BTW, I tried the idea of changing the ceiling value according to voltage. I had to rearrange a bunch of other code to make room, but I think it’ll work… ish. I’ve only tried a very coarse correction table so far, and due to the variability in voltage measurements, it tends to make moon mode blink brighter or dimmer every few seconds.

This could be fixed by using a bigger table and/or taking an average of several voltage readings, but those both take more space. I’ll probably at least try a slightly bigger table though.

The problem right now is that I’m too sleepy for any complicated math. I’ve got a non-linear curve with an unknown equation (the power to the emitter rising during each pulse) which changes shape according to another non-linear curve (voltage drop), and the only way I can correct it involves another non-linear curve (PFM response curve, roughly 1/x shape). Given these three, I’m trying to make a fourth curve which takes the first three as input and returns a result which is as close to flat as possible. And then quantize that fourth curve into a relatively small table.

That’s too much math for me to do this morning.

I would really love it if this driver had a single 7135 chip available for handling moon mode. (like RMM’s moonlight special, only on a FET driver)

Edit: So, I tried a simpler approach… added a lowpass filter instead. It seems to work pretty well. The PFM level will simply ramp up/down by 1 any time the voltage reading says it’s not right. That means the flicker is very small, and when it does change it’s pretty smooth. If the voltage flips rapidly above and below a threshold, the PFM level will just hang out somewhere in the middle. Plus, it looks cool smoothly ramping up on boot.

OTOH, I’m seriously scraping the bottom of the barrel now for spare bytes. It’s at exactly 1024 and I don’t see anything else I can reduce in size without dropping features.

wight wrote:
Changing the subject a little, … I think that using the register names instead of hex [wherever reasonably feasible] would make the code a tiny bit more accessible. ?

Oh, yes, probably. But I didn’t know that was a usable symbol in avr-gcc so I used the hex value instead. I think it’s probably fine either way as long as it’s documented / commented.
wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

wight wrote:
I’ve got to go to bed, but here’s a real hackjob I’ve been working on this evening. It compiles, but I don’t have time to flash it and assemble a driver before bed. There may be serious oversights.

This is intended as a proof-of-concept for a VaraPower style driver (rotary potentiometer chooses brightness) which includes low-voltage-warning and low-voltage-shutdown.

Here is what I did [thankfully not written in the order I did it]:

  1. used “STAR_1.1.c” as a base
  2. stripped out everything that I don’t think this style of driver needs, modes, turbo, etc
  3. replaced the main loop with the two-way ADC loop from the Nov 4, 2014 [1263cd98f9] version of MTN_momentary_temp.c
  4. changed the way the ADC loop switches ADC channel so that it toggles Vref back and forth as well – I think/hope? Bitwise operations are difficult for me.
  5. replaced the temperature stuff with a command to just patch that ADC value to PWM_level. Maybe ideally there would be a rolling average here, but that can come later.
  6. hacked up the LVP flashing to go full brightness during flashes
  7. hacked up the LVP to semi-function without modes. Ideally it should flash quickly 3 times every ~3 seconds until we hit critical, then flash 10 times and shutdown.
  8. copied and pasted a couple of variable initializations

  • There are certainly some power savings tricks missing.
  • I actually don’t see why we couldn’t add the potentiometer as a third ADC input and keep the temp monitoring.
  • Come to think of it, now I can imagine how to include “stepdown” in a way that makes sense. After the 3 quick flashes, implement a ceiling value. Progressively half it or whatever is reasonable. Potentiometer throw remains the same, but the actual PWM value produced is capped @ whatever whenever it is set.
    if (ADC > ceiling_value) {PWM_LVL = ceiling_value} else {PWM_LVL = ADC}
    Bingo?

As far as hooking it up… I think PB2 (eg just like normal) should be voltage monitoring and PB3 [Pin 2, Star 4] should be for the pot. You hookup the pot between Vcc and GND with the sweeper hooked up to PB3.

Here it is: http://photo.jesusthepirate.com/blf/VeraPunk/v002.c

I’m sorry in advance. Wink Wink Wink

OK so this totally didn’t compile. Not sure what was going on, sometimes AVR Studio can get confused and compile a nice little nothing instead of what I pasted in there. Also it was pretty late at night. Wink

This version compiles v004 but does not seem to work correctly. I get around 50% output and no low battery flashes. Does anyone see an obvious reason why?

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

I think I found a small typo in “MTN_momentary_temp.c”.

// MUX 01 corresponds with PB2, 02 for PB3. Will switch back and forth

0×02 is actually PB4, right?

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

Cereal_killer
Cereal_killer's picture
Offline
Last seen: 1 year 5 months ago
Joined: 07/22/2013 - 13:10
Posts: 4005
Location: Ohio

Is there an off-time version with strobe?

 RIP  SPC Joey Riley, KIA 11/24/14. Now I am become death, the destroyer of worlds.

wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

wight wrote:
OK so this totally didn’t compile. Not sure what was going on, sometimes AVR Studio can get confused and compile a nice little nothing instead of what I pasted in there. Also it was pretty late at night. Wink

This version compiles v004 but does not seem to work correctly. I get around 50% output and no low battery flashes. Does anyone see an obvious reason why?

OK, several small changes and this is where I’m at now: v009.c

It’s still definitely not right.

  • I’m able to adjust the output PWM with the pot, but I don’t think I’m getting 100% duty cycle even though the voltage on the input pin is the same as Vcc. (I did not check duty cycle with a scope though).
  • LVP is definitely not working correctly, but so far it has never turned the light off in any version. The best I ever got was around 10 flashes and then 100% duty cycle and unresponsive to the brightness pot. Now….
  • Right now I’ve got some constant pulsing going on, but that wasn’t happening until the latest version… I think.

There are a lot of things I want to tweak, but none of them should be causing these issues… in intermediate versions it felt almost like PB2 was floating, but of course it was not – I checked multiple times with a DMM.

I’m starting to feel like I’m going backwards. I understand better than ever what all this stuff is supposed to be doing, but less than ever why it’s actually doing what it’s doing. It’s all hacked up copy-paste stuff, so maybe significant re-writes would help. In the context of a flashlight where the brightness is controlled by a potentiometer none of the original battery monitoring code makes a ton of sense. I think removing it and starting with a clean slate may be the smart move now.

I guess I’d better disable voltage monitoring again and test to see whether I get full duty cycle with that disabled. Either way the answer is still probably to remove all voltage monitoring code, troubleshoot any remaining problems, then add voltage monitoring back in.

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

Cereal_killer wrote:
Is there an off-time version with strobe?

The only one I’ve seen is the one I made in the last couple days… but it’s kind of, um, deviated from its STAR roots. I wrote it to use on my Cypreus, and it’s a tad bit heavy on the blinkies. I haven’t made any which are more appropriate for general purpose use.

I’d suggest copying the strobe bits back into STAR, but the strobe functions are pretty trivial and the code is pretty far from where it started. I suspect my version would only be useful for ideas, not for actual code.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

wight wrote:
It’s still definitely not right.
  • I’m able to adjust the output PWM with the pot, but I don’t think I’m getting 100% duty cycle even though the voltage on the input pin is the same as Vcc. (I did not check duty cycle with a scope though).

It’s an analog-to-digital signal, converted on cheap hardware, and it’s pretty much guaranteed to be noisy and +/- 10% off spec. It’ll be even noisier if the MCU is doing anything during the conversion. So, it’s safe to assume that you’ll need to scale the values and run a lowpass over them to get any reasonably-sane output.

As for LVP, I think you’re correct that you need to just turn it off until the other functions are working.

Also, it might be helpful to declare all your global variables as volatile. Since the source file isn’t used as a module by other files, declaring globals as static has no effect. Volatile, however, tells the compiler to assume the variable is being changed by other threads or interrupts, and should never be trusted or cached.

I see something else which could be causing issues too…

while(1) {
    if (ADCSRA & (1 << ADIF)) {
        ...
    }
    // Start conversion for next time through
    ADCSRA |= (1 << ADSC);
}

It looks like you’re re-starting the conversion again before it has a chance to finish. The re-start should probably be inside the if, not after it.

You could also just busy-wait on the result, since the code isn’t doing anything else at the time. For example, this is how I block until I get a voltage reading:

uint8_t get_voltage() {
    // Start conversion
    ADCSRA |= (1 << ADSC);
    // Wait for completion
    while (ADCSRA & (1 << ADSC));
    // Return the raw value, caller can decide what to do with it
    return ADCH;
}
wight
Offline
Last seen: 1 year 2 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

I’m not sure if the ADC is as noisy as you think. It’s definitely noisy, but my small experience with MCUs and ADC’s tells me that ADC noise is not the core of any of the actual problems. The driver should behave with no smoothing, it should just be a little rough. I think, heh. I definitely plan to come back and do something about the noise.

Thanks for the poitners on declaring as volatile. I’ve had that explained to me before, but lost track of it. I’ll go through and clean it up.

That final point of yours about the structure of the loop is right on the money. That is clearly a bad setup, I see it now that you have pointed it out. Either blocking for it or moving it inside the if conditional seem equally good to me for this setup. For now I’ve moved it inside the if conditional.

Most recent results:

  1. With VOLTAGE_MON undefined in v009 the pulsing goes away AND I’m able to turn the output all the way up with my pot. And all the way down.
  2. No change after moving:
    ADCSRA |= (1 << ADSC);
    It was still a good point though.
  3. v011 has batt_adc_ticks declared as volatile. It’s the only variable which should be able to change unbeknownst do the main loop. No change.
  4. I went ahead and commented out the entire mechanism that does anything to the output based on voltage monitoring, but left VOLTAGE_MON defined so that the ADC would toggle back and forth. Sure enough, the pulsing is gone – time will tell whether that was ADC noise or a screwup(s) in the LVP section I commented out. In the meantime I noticed that with this setup I still have upper and lower limits on what I can do with the pot. It won’t turn the output all the way down OR all the way up. I’m thinking that I need to do two readings each time I change Vref and discard the first reading.

We’ll come back to that thought though, it’s time to hang up the hat for the day. Thanks for your help ToyKeeper.

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

To mostly eliminate the noise, it works well to do something like…

  if (ADCH > PWM_LVL) { PWM_LVL ++; }
  else if (ADCH < PWM_LVL) { PWM_LVL --; }

It works pretty well as a lowpass filter, and adds a nice ramp effect when the value changes really quickly.

Or you could, you know, resolve the cause of the noise. But sheesh, who wants to do things properly? Smile

JonnyC
JonnyC's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 01/14/2011 - 19:12
Posts: 1148
Location: Green Bay, WI - USA

wight wrote:
I think I found a small typo in "MTN_momentary_temp.c".
// MUX 01 corresponds with PB2, 02 for PB3. Will switch back and forth

0x02 is actually PB4, right?

Yup, thanks!  I'll change that comment.

JonnyC
JonnyC's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 01/14/2011 - 19:12
Posts: 1148
Location: Green Bay, WI - USA

Cereal_killer wrote:
Is there an off-time version with strobe?

I never added strobe to any of mine.  I believe RMM has a strobe option in his versions which I never included back in mine, and of course the other guys here have added their own strobes.

This is what RMM did in the "int main" routine, changed this...

Quote:
set_output(modes[mode_idx]);

to...

Quote:
if (modes[mode_idx] == 254) {

// Strobe.  The program will stop here, you will lose the voltage monitoring feature

while (1) {

set_output(255);

_delay_ms(20);

set_output(0);

_delay_ms(60);

}

} else {

set_output(modes[mode_idx]);

}

A mode of "254" will become a strobe then.  I can add this to STAR and STAR_off_time if it works well enough.

 

As for strobe, what is the most effective one?  Does the 20 ms on and 60 ms off work effectively?  Does anyone know if this can be done via PWM by dividing the clock (really slowing down the PWM)?

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

JonnyC wrote:
… This is what RMM did in the “int main” routine, changed this…
// Strobe.  The program will stop here, you will lose the voltage monitoring feature
A mode of “254” will become a strobe then.

As for strobe, what is the most effective one?  Does the 20 ms on and 60 ms off work effectively?  Does anyone know if this can be done via PWM by dividing the clock (really slowing down the PWM)?

It’s not necessary to lose voltage monitoring just because the light is in a blinky mode. In mine, I just light up, wait, turn off, wait, then proceed with the main loop (which allows voltage monitoring to happen), then it happens again next time the loop comes around. Instead of using modes[mode_idx] as a code to enter strobe mode, I use mode_idx itself (with #defines to decide how to map indexes to behaviors). The modes[mode_idx] value represents the strobe speed. This way, you can have strobes of different speeds without using mode space in the ROM.

Here is what I’m using, an off-time firmware with strobe modes:

http://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/files/h...

That’s the one which has deviated the furthest from STAR though. Its predecessor, ToyKeeper/s7/s7.c, is closer (but is on-time based). Also, they both use party strobes (freezes motion) instead of tactical strobes (for stunning people), so you’d need to change the duty cycle.

From what I’ve heard/read, the most effective tactical strobe is 10Hz with a 50% duty cycle. So, something like this should work:

#define OWN_DELAY
#define SOLID_MODES 4
#define TACTICAL_STROBE_MODES 2+SOLID_MODES
...
const uint8_t modes[] = {
    MODE_LOW, MODE_MED, MODE_HIGH, MODE_TURBO,  // solid modes
    50, 25,  // 10Hz strobe, 20Hz strobe  (1000 / 2 / X == strobe speed)
};
...
int main(void)
{
    ...
    while(1) {
        if(mode_idx < SOLID_MODES) { // Just stay on at a given brightness
            PWM_LVL = modes[mode_idx];
            sleep_mode();  // the WDT will wake us up for voltage checks
        } else if (mode_idx < TACTICAL_STROBE_MODES) { // strobe mode, fixed-speed
            PWM_LVL = 255;
            _delay_ms(modes[mode_idx]);  // requires OWN_DELAY
            PWM_LVL = 0;
            _delay_ms(modes[mode_idx]);
        }
        #ifdef VOLTAGE_MON
        if (ADCSRA & (1 << ADIF)) {  // if a voltage reading is ready
            ...
        }
        #endif
    }
}

As for using PWM to do strobes… it should be possible down to 2Hz (I wrote a script to do the math a while back), but it would require setting the CPU to its absolute slowest clock speed. I haven’t looked up if that can be done from inside the program or if it needs fuses set. So, it might interfere with the PWM on regular modes, and the only real benefit is that it would use slightly less power.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 25 min 53 sec ago
Joined: 01/12/2013 - 14:40
Posts: 10654
Location: (469219) 2016 HO3

Oops, I just realized/remembered that STAR doesn’t know at compile time how many modes there will be. That certainly makes it harder to use the mode index to decide what kind of behavior to use.

Pages