luxdrv - custom modes driver firmware with ramping

268 posts / 0 new
Last post

Pages

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany
luxdrv - custom modes driver firmware with ramping

This is about programming a driver yourself with all the modes you want; just like Tido's thread "How To Build a Flashlight With Perfect Modes (picture heavy)". It got quite lengthy, so I started a new one for my driver program.

I finally found the time to program my own driver. After playing with the three pocket XM-L lights in the last week I found it good enough to publish it here.   

It has less features than Tido's, so it leaves room for improvements (meaning that there's indeed quite some free space left to do so). It doesn't have any battery monitoring yet.

It implements sixty545's UI(post #254), which after some testing I found very nice. Gives you lots of modes without the need to cycle through all of them when switching between the favourites. Leaving the light on for only a short time (<2s) and the switching it off again will bring you to the next mode when you switch it on again. Leaving it on for longer will memorize this mode for the next time; but if you change modes again it will start from the first mode in the mode order. If you put your favourite modes to the front, this is a quite nice UI I think.

Current modes are moon-medium-high- 6 levels of brightness -strobe-beacon-timer. 

As a special mode I added a 5-minute timer - partly for fun, but I do need a 5-minute timer relatively often.

One of the PROs of this driver is the wide EEPROM wear leveling; writes are spread over 32bytes, and only 1-3bytes are written each time the light is switched on. A ramping mode might be feasible that way. 

It is supposed for/tested on the NANJG 105C (2.8A) and NANJG 101-AK (1.05A+) drivers using AMC7135s and the ATtiny13A micro-controller.

Tido's thread mentions everything you need, so here's a short version:

  • Driver: NANJG 105C or  NANJG 101-AK or similar
  • Programmer for flashing the program to the controller: there seem to be some available for 4$ on ebay (search for "avr programmer").
  • a clip for contacting the controller, search for "soic8 clip" at ebay
  • Software: I use AVRstudio4 with WinAVR

The driver program is just a C file; you could create a new project for the ATtiny13A using the wizard and then just copy&paste the contents into that projects C file.

Since I am very sensitive to PWM (I easily notice 2kHz PWM...), I meanwhile use a CPU frequency of 4.8MHz with a PWM frequency of 9.4kHz, difficult to notice even if I want to Smile That means a low fuse of 0x75 (and I use a high fuse of 0xff) and the lowest usable PWM value is 5. Shorter PWM pulses are too short to activate the AMC7135s.

UPDATE: luxdrv 0.22 with ramping

I implemented ramping, have played with it for a while and found it nice, so here's the new version officially:

Standard modes are now (can be easily changed of course): 
  moon - medium - high - ramping - use selected level - strobe - beacon - timer
Tapping the switch while ramping will select that level. The ramp is actually 25 levels 'only', so you can see it stepping up&down. Brightness doubles about every 5 steps (the darkest levels are spaced a bit wider).

I also implemented sixty545's idea of skipping the 1st mode when starting over after already being in 1st mode. Also changed the wear leveling method; it writes even a bit less bytes now, but it does write 25 bytes per ramp, so you probably shouldn't use that for hours (~700 writes per EEPROM cell per hour).

UPDATE: luxdrv 0.30 - added battery monitoring

I implemented battery monitoring:

  • When the battery (under load) goes below ~3.0V, the light automatically steps down in brightness (halves the output); the reduced load usually gets the battery voltage above 3V again. When it falls below that threshold agan, output will be halved again - and so on.
  • Beacon mode has a battery indicator: Before actually starting beacon mode, a number of (low intensity) blinks indicates battery level (without load), ~12 blinks is full, ~5 blinks is nearly empty. It's about one blink for every 0.1V over 3.0V (cell voltage *without load*).
  • Note that those values are not accurate due to production variances in the microcontroller's internal voltage reference.

Update: luxdrv 0.30b - improved config, const progmem, no dummy any more, timer removed, 4 main modes as default

Driver download links:
luxdrv 0.1
 
luxdrv 0.22 with ramping
luxdrv 0.30b, added battery monitoring 

Edited by: DrJones on 03/13/2013 - 09:05
Microa
Offline
Last seen: 2 hours 30 min ago
Joined: 06/29/2011 - 21:20
Posts: 228

Dear DrJones,

Many thanks for your sharing of your codes. I have just downloaded your source code and will try it out later. I am building a head lamp which requires temperature monitoring the LED. Being an uC dummy, I would like to ask you to put this feature in your to do list. I wish the driver will switch to the next lower light level when the temperature reach the threshold. No blinking as the driver which I modified the battery monitor to a temperature monitor.

Thanks in advance.

Microa

Chicago X
Chicago X's picture
Offline
Last seen: 4 years 2 months ago
Joined: 07/22/2011 - 16:13
Posts: 4013
Location: See Name

Thanks very much for sharing your valuable work.  This adds so much more flexibility to the ubiquitous 7135-based drivers.

 

 Schönen Dank!

http://wardogsmakingithome.org/index.html

War Dogs, Making it Home - Rescue Dogs for Returning Vets

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Microa, please give a bit more info then, i.e. the rule for ramping down, e.g. like "if voltage >0.7v, go down a level", and I could try.

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Then again, you could modify Tido's firmware to get rid of the blinking:

Find the lines  (line number 555 for me):

while(1){
     // give a short blink every five seconds
     PWM_LVL = pwm;
     _delay_ms(5000);     
//     PWM_LVL = 0;           <---
//     _delay_ms(100);        <---
#ifdef LOWBAT_RAMPDOWN

and prepend "//" to the marked lines as shown above. 

Microa
Offline
Last seen: 2 hours 30 min ago
Joined: 06/29/2011 - 21:20
Posts: 228

DrJones, The NTC resistor is 10K at 25C and about 3.3K at 70C. A 5V of Vref is applied to the voltage devider. For setting at 130/255 of 1.1V of the uC voltage reference, the light level will go down if voltage of the NTC drops lower than 0.56V.

Microa
Offline
Last seen: 2 hours 30 min ago
Joined: 06/29/2011 - 21:20
Posts: 228

Thanks DrJones, I will try to modify the code to get rid of the blinking.

Microa
Offline
Last seen: 2 hours 30 min ago
Joined: 06/29/2011 - 21:20
Posts: 228

It works.Laughing

I modified the code and it works. The driver ramps down the light level without blinking.

Thanks a lot.

JonnyC
JonnyC's picture
Offline
Last seen: 1 week 5 days ago
Joined: 01/14/2011 - 19:12
Posts: 1137
Location: Green Bay, WI - USA

Thanks for this post!  I wanted to do the same kind of post, but my code (created by using Tido's as a reference) is much simpler and doesn't have the best EEPROM wear leveling (as Tido's seemed to write the same byte on each turn-on anyways, IIRC, unless I read the code wrong).  However, looking at yours, I do see you doing true wear leveling, and it is quite ingenious! (well, it took me a while to realize how you did it - had to freshen up on my bitwise understanding)

The best I could come up with was changing a byte from 0 to 1 when doing the short presses while working through the bytes (one-click: 10000, two: 11000, three: 111000, etc.), and then clearing them all back to 0 when the current mode is saved.  Not exactly the best, but better than wearing out the same byte on every short press.  Yours is much better though, and using the 0x80 bit as the short-press indicator is pretty awesome - one of those "why didn't I think of that?!" moments.  I'll have to find a way to incorporate your logic into my UI setups.

Tido
Offline
Last seen: 9 months 4 days ago
Joined: 05/28/2010 - 15:28
Posts: 189
Location: Berlin, Germany

JonnyC wrote:

Thanks for this post!  I wanted to do the same kind of post, but my code (created by using Tido's as a reference) is much simpler and doesn't have the best EEPROM wear leveling (as Tido's seemed to write the same byte on each turn-on anyways, IIRC, unless I read the code wrong).  However, looking at yours, I do see you doing true wear leveling, and it is quite ingenious! (well, it took me a while to realize how you did it - had to freshen up on my bitwise understanding)

The best I could come up with was changing a byte from 0 to 1 when doing the short presses while working through the bytes (one-click: 10000, two: 11000, three: 111000, etc.), and then clearing them all back to 0 when the current mode is saved.  Not exactly the best, but better than wearing out the same byte on every short press.  Yours is much better though, and using the 0x80 bit as the short-press indicator is pretty awesome - one of those "why didn't I think of that?!" moments.  I'll have to find a way to incorporate your logic into my UI setups.

Yes, my driver on average does one erase/write cycle per cell and click. Wear levelling  is only done on cells that may see more than one write when the light is on (click type detection and mode change sequences in newer versions). I tried using wear levelling the way DrJones does it, but it turned out to eat too much EEPROM and program flash space if I wanted to fit all the functionality I have now into the BLF-VLD. It is the same thing with cramming independent state information into one byte using bit operations. Sure, you have one less variable sitting in the EEPROM, but you pay for it in program flash because you need more instructions to access and store the information.

Anyway, the ATtiny's EEPROM is rated for a guaranteed durability of 100000 erase/write cycles. Even at a hundred clicks per day, it would last almost three years. And this is only the guaranteed minimum, the real durability is probably five to ten times that.

BTW, writing a zero to a cell is not just erasing it, it is a full erase/write cycle. If you just want to erase it, you can set EEPM1=0 and EEPM0=1 in EECR, but the erased cell will then read 0xff. To only write without erasing, you set EEPM1=1 and EEPM0=0. You can write multiple times to a cell without erasing it first, but you can only write zeroes (e.g. you can overwrite 0xff with 0xfe, but not the other way around). This will be less stressful for the cell, as it is the erasing that causes the wear, but you'll have to invert your program logic.

E1320
E1320's picture
Offline
Last seen: 2 weeks 5 days ago
Joined: 03/30/2011 - 05:26
Posts: 3369
Location: New Hampshire

Thanks for sharing your code DrJones and thanks again Tido for planting the seed that made this all possible. Hopefully I will be able to share my dream program with everyone here soon.

I am already visualizing the duct tape over your mouth.

JonnyC
JonnyC's picture
Offline
Last seen: 1 week 5 days ago
Joined: 01/14/2011 - 19:12
Posts: 1137
Location: Green Bay, WI - USA

Thanks for that info Tido!

krisirk
Offline
Last seen: 1 year 2 months ago
Joined: 11/07/2011 - 19:53
Posts: 10
Location: North Dakota

DrJones,

 

Thanks for posting your program.  I flashed a generic 3x7135 board last night with your program and it worked like a charm.  Using the highest PWM frequency you have listed and a Q5 XR-E I was able to get light using a PWM setting of 1.  The next driver I'll flash is an 8x7135 NANJG 105C to be used with an XM-L in a Trustfire T2, assuming everything fits properly.

 

Thanks again for writing this program,

 

Kris

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Interesting. Maybe those 0.4 µs pulses are not sufficient for 8 AMCs, but for 3...

What fuses did you use?

krisirk
Offline
Last seen: 1 year 2 months ago
Joined: 11/07/2011 - 19:53
Posts: 10
Location: North Dakota

To be honest, this was my first time doing any Atmel programming so I had just installed a fresh copy of AVR Studio 5 and didn't change any fuse settings.  The chip on the board is a low voltage version (1.8V min instead of 2.7), an Attiny13V.  

 

Perhaps with the stock fuse settings it defaults to a slower frequency?  I'll gladly check the settings when I get home tonight if you'd let me know where I should check.

 

Kris

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Yes, with stock settings you should get 2.35 kHz PWM frequency.

I think the timing should be off in your setting then; it was compiled for 4.8MHz CPU frequency, but it runs on 1.2MHz. How does strobe look? How long does the beacon take between two flashes? How long does the 5-min timer run?  

Edit... Then again, I don't know what stock settings the driver has... the above mentioned are the stock settings for new bare ATtiny13s.

krisirk
Offline
Last seen: 1 year 2 months ago
Joined: 11/07/2011 - 19:53
Posts: 10
Location: North Dakota

I just looked at the code again and noticed that you had the values for the low fuses listed after the frequencies.  I'll try to find where to change the setting and make it 0x75 to run at 4.8 MHz, then try the tests you mentioned.

 EDIT:  I'm installing AVR Studio 5 on my work computer as I type this.  I should be able to find where the fuses are set once it is installed.

Kris

JonnyC
JonnyC's picture
Offline
Last seen: 1 week 5 days ago
Joined: 01/14/2011 - 19:12
Posts: 1137
Location: Green Bay, WI - USA

I run mine at 4.8 as well, and set the fuses this way...

avrdude -c usbtiny -p t13 -Ulfuse:w:0x79:m -Uhfuse:w:0xed:m

Not sure if I got all of the fuses right, but it works Smile

krisirk
Offline
Last seen: 1 year 2 months ago
Joined: 11/07/2011 - 19:53
Posts: 10
Location: North Dakota

DrJones wrote:

Yes, with stock settings you should get 2.35 kHz PWM frequency.

I think the timing should be off in your setting then; it was compiled for 4.8MHz CPU frequency, but it runs on 1.2MHz. How does strobe look? How long does the beacon take between two flashes? How long does the 5-min timer run?  

Edit... Then again, I don't know what stock settings the driver has... the above mentioned are the stock settings for new bare ATtiny13s.

 

It turned out that my stock frequency was actually 9.6 MHz.  I changed it to 4.8 MHz using the GUI in AVR Studio.  This set the fuses to H=0xFB, L=0x71.  I'm still able to get light at a PWM of 1, but it is quite dim.  I can look directly at the emitter through an 8 degree optic.

 

I was able to test the other modes as well.  The beacon is 10 seconds, the timer works out to a little over 5 minutes, and the PWM frequency seems to be ~8.5 KHz if the PWM is set to 1-31, and ~17 KHz if set to 32-254.

 

My multimeter doesn't like the strobe, so I can't give an absolute value for that.  It did look pretty good though.  If the rest of the timings are on then it must be pretty close as well.

 

If there's anything else you'd like tested I'll give it a shot.

 

Kris

csshih
Offline
Last seen: 1 year 1 month ago
Joined: 10/13/2011 - 15:21
Posts: 104
Location: San Jose

DrJones wrote:
One of the PROs of this driver is the wide EEPROM wear leveling; writes are spread over 32bytes, and only 1-3bytes are written each time the light is switched on. A ramping mode might be feasible that way. 

 

I am curious if there have been lights whose EEPROMs have worn out, hrm..

C

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

I implemented ramping now; it's actually only 25 levels of brightness ramping up and down within 4s each (so you see it jumping); tap at the desired level and you get that mode fixed. It costs about 200 bytes, so it's getting full now... 880 bytes used (including timer).

It writes 25 bytes per ramp, wear leveling sure comes in handy here.

I'll play with it for some days and then post the code here.

JonnyC
JonnyC's picture
Offline
Last seen: 1 week 5 days ago
Joined: 01/14/2011 - 19:12
Posts: 1137
Location: Green Bay, WI - USA

Ramping, why didn't I think of that? So once it hits the right level, you turn the light off then back on and it goes to that level?

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Yes... My mode order is currently

moon, mid, high, ramp, use ramped mode, strobe, beacon, timer

(can be changed of course) 

krisirk
Offline
Last seen: 1 year 2 months ago
Joined: 11/07/2011 - 19:53
Posts: 10
Location: North Dakota

DrJones wrote:

I'll play with it for some days and then post the code here.

 

I'd gladly test the brightness ramping code when you post it.

 

Kris

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

I'm currently not happy with it: Occasionally there's a glitch when trying to lock the ramped level; when unlucky, the power goes out while writing to the EEPROM, the erase cycle gets through, but not the write, resulting in a wrong PWM level.

I wonder if brown-out detection could help here (I didn't activate it).

I think I want to rewrite some parts of the code. Might even save a few bytes.

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Well then, here's a new version with ramping. It's considered beta.

Download: luxdrv v0.21 with ramping

EDIT: Uh-oh, a bug... inhibited the correct mode change on fast taps when ramping.

Download: luxdrv v0.22 with ramping

DrJones
DrJones's picture
Offline
Last seen: 1 year 4 months ago
Joined: 01/05/2011 - 13:30
Posts: 1044
Location: Frankfurt, Germany

Well, I used it for a while now and I like it, so I updated the 1st post.

I recently played with a light using an unmodified Nanjg105C - I guess I'm already too used to the smarter firmwares like Tido's or mine to be happy with that. Wink

I'd be happy to get some feedback from you.

chiefinspectorfinch
chiefinspectorfinch's picture
Offline
Last seen: 1 month 4 weeks ago
Joined: 09/27/2010 - 14:33
Posts: 531
Location: Croatia, country with clero-fascist government

I'm wondering would it be possible to use Attiny13 and 7135 based drivers in different way. Idea is to make use of more attiny13 ports for "enabling" individual (or more than one) 7135 chip via vdd pin and thus avoid using pwm completely or just use it for low modes when only one 7135 would be enabled. This would also require hardware modification of driver by cutting traces to vdd pin and connecting them to previously unused attiny ports. For example on 4*7135 driver we could have a configuration with this modes: low (1x7135) / med (2x7135) / high (4x7135) with 3 ports. Since I have very little experience in programming I'm not sure if this is even possible with attiny13...

As I already noticed in post (http://budgetlightforum.com/node/1853#comment-97001) that some AMC7135 drivers use PWM even ih high mode, but if I understand correctly when using luxdrv or BLF-VLD level 255 means that practically no pwm is used since duty is 100%.

 

 

 

 

Society is like a pot full of nuts and bolts, finest pieces always end up on the bottom...

 

Tido
Offline
Last seen: 9 months 4 days ago
Joined: 05/28/2010 - 15:28
Posts: 189
Location: Berlin, Germany

chiefinspectorfinch wrote:

I'm wondering would it be possible to use Attiny13 and 7135 based drivers in different way. Idea is to make use of more attiny13 ports for "enabling" individual (or more than one) 7135 chip via vdd pin and thus avoid using pwm completely or just use it for low modes when only one 7135 would be enabled. This would also require hardware modification of driver by cutting traces to vdd pin and connecting them to previously unused attiny ports. For example on 4*7135 driver we could have a configuration with this modes: low (1x7135) / med (2x7135) / high (4x7135) with 3 ports. Since I have very little experience in programming I'm not sure if this is even possible with attiny13...

As I already noticed in post (http://budgetlightforum.com/node/1853#comment-97001) that some AMC7135 drivers use PWM even ih high mode, but if I understand correctly when using luxdrv or BLF-VLD level 255 means that practically no pwm is used since duty is 100%.

That would be too coarse, because even a single 7135 still delivers 350mA, which produces quite a lot of light. There would practically be no low mode. But there is an solution to that...

I have an 8x7135 lying around, where only one of the 7135s is driven by PWM. The other 7 are divided into three groups (1, 2 and 4) which are controlled by digital I/O. This extends the PWM-range by 3 bits, which means that it can go from a very low low (~1.4mA) to a whopping 2.8A. As a side effect the LED's efficiency increases marginally at low levels, because it only sees pulses of 350mA, not 2.8A.

chiefinspectorfinch
chiefinspectorfinch's picture
Offline
Last seen: 1 month 4 weeks ago
Joined: 09/27/2010 - 14:33
Posts: 531
Location: Croatia, country with clero-fascist government

Excellent, that's what I had on mind ("avoid using pwm completely or just use it for low modes when only one 7135 would be enabled").

Did you make modified program or was it "off the shelf" like that ? Managing modes in this way improves efficiency and there is no pwm on all but low modes. If I understand correctly only possible downside is lack of strobe/sos modes in higher power (i presume they are possible to obtain in single 7135 mode)

Society is like a pot full of nuts and bolts, finest pieces always end up on the bottom...

 

Tido
Offline
Last seen: 9 months 4 days ago
Joined: 05/28/2010 - 15:28
Posts: 189
Location: Berlin, Germany

I simply made an experimental branch for the BLF-VLD. It just took some fiddling with the set_pwm function, so all the disco-modes still use the max. light level. The only mode restricted to the true PWM is the fading one. Expanding it to make use of the extra three bits just ate too much program flash.

If I ever get around to release another BLF-VLD version, this will be included.

Pages