D.I.Y. Illuminated Tailcap - gChart Editions

153 posts / 0 new
Last post
moderator007
moderator007's picture
Online
Last seen: 5 min 18 sec ago
Joined: 12/23/2012 - 04:47
Posts: 3270
Location: North Carolina

Nice job gchart!
Especially like the decreasing lighted led’s to battery level indicator. Thumbs Up

Cereal_killer
Cereal_killer's picture
Offline
Last seen: 1 month 3 weeks ago
Joined: 07/22/2013 - 13:10
Posts: 4005
Location: Ohio

SUPER COOL!

Seems like with probably just a few very minor code changes you could use half green and half red LEDs and have a tail ring that fades from green to yellow to red.

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

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Cereal_killer wrote:
SUPER COOL!

Seems like with probably just a few very minor code changes you could use half green and half red LEDs and have a tail ring that fades from green to yellow to red.


The problem with fading is that requires ramping PWM up and down, which requires the MCU to be awake. Awake, the 416 will probably use 1mA (@3.3MHz). Asleep, it should be around 1uA. (datasheet pages 439 and 445, not my measured values). If battery drain isn’t too big of a concern, that definitely is a possibility!
gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Ok… I tested it in-flashlight. It’s a Convoy M1 with a Nanjg105c & 750 Ohm bleeder. Results seem mostly positive.

Firstly, it works. But a few observations:

  • I’ll definitely need to adjust the voltage detection levels. A 4.09V battery gave 6/8 LEDs. A 3.54V battery gave 3/8 LEDs.
  • The LEDs are dim during the animation, I’m guessing because the MCU is taking up most of the current. Not a big deal. I might even remove the animation. Not sure yet.
  • The first voltage check reads low. This is despite the fact that I take 16 ADC readings and trash them, then grab 8 readings and average them. I guess it’s just because it’s taking the reading on the coat tails of the animation? Dunno, I can probably code around it.
  • I can probably reduce the MCU current draw in active mode (ie, animation) by reducing the CPU frequency and making sure I have some other things disabled (like BOD). Freq is currently 3.3MHz, I think. I just rolled with the default, which I think is 20MHz with a divider of 6. Any idea whats a safe, low frequency to use?

MikeMacD
Offline
Last seen: 4 days 16 hours ago
Joined: 05/15/2018 - 01:53
Posts: 59
Location: Texas, USA

gchart,

This is sort of off topic but what do you have your buck driver attached to for power? I’m looking for a similar setup.

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

MikeMacD wrote:
gchart,

This is sort of off topic but what do you have your buck driver attached to for power? I’m looking for a similar setup.


This. It’s very basic, but it works for what I need right now.
gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

An update…

I managed to decrease the MCU power draw considerably by changing the main clock to be driven from the 32.767 KHz internal ULP (ultra low power) RC oscillator instead of the prescaled 20MHz one.

I also managed to get a good grasp on the ADC readings by using the 8 LEDs to display the significant digits of the ADC readings in binary (each LED representing one bit of the ADC reading). It worked really slick. I took 7 measurements across the typical voltage range and got a great trend line with an R^2 value of 0.99.

So now that I have a calibrated formula, I just need to plug that into the source code, re-uploaded, and we should be in business!

MikeMacD
Offline
Last seen: 4 days 16 hours ago
Joined: 05/15/2018 - 01:53
Posts: 59
Location: Texas, USA

Thanks! What are you using as a power source?

clientequator
clientequator's picture
Online
Last seen: 8 min 8 sec ago
Joined: 12/05/2018 - 15:42
Posts: 167

Mr gchart I like your project very much! I am looking forward to more update and improvements!!

Lothar
Lothar's picture
Offline
Last seen: 4 days 8 hours ago
Joined: 10/26/2011 - 11:22
Posts: 521
Location: Stellenbosch, South Africa

Give that man a Bells! Beer
Watching close with interest

Current Collection:

BLF: BLF-GT90, BLF-GT70 (CW Sliced), BLF GTmini, BLF-LT1; 

BTU: Shocker (3 x SST-40 @ 8A)

Solarforce: L2P (XM-L2 U3 @ 4A), MPP-1 (XP-L HI @ 6A), MPP-3 (3 x XM-L2 U2 @ 12A), M6 (Nichia 319A @ 6A), M8 (XHP-50.2 @ 9A), 9x (9 x XM-L2 U2 @ 2A)

Coming Soon: Lumintop: BLF-GT4; 

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Updates:

  • I made a few code tweaks yesterday and re-flashed it. I think it’s all done now! I put in several batteries at various voltages and the LEDs are lighting up exactly as they should. Big Smile
  • Switching to using the 32.768KHz oscillator for the clock really helped with power consumption during active state (and a bit in standby as well). The LEDs are no longer dim during the animation, as there is plenty of current available now
  • I used LED series resistors with less resistance than what I desired (used 30K, probably should have used 90K or so). With all the LEDs lit during standby, current consumption is 0.35mA (I typically aim for 0.12-0.18mA depending on the LED colors used). I think almost all of that is going to the LEDs. Only an immeasurable amount to the MCU (well, immeasurable with my DMM that only reads to 0.00mA).
  • During the active state with animation (one LED lit), the consumption is 0.05mA. That’s actually about how much current I figure the LED itself is consuming… battery voltage at 4.1V with measured LED vF of 2.5V using a 30K Ohm resistor: (4.1V – 2.5V)/30000Ω = 0.05mA. So even during active state (not sleep), the MCU is using almost no current.

Cereal_killer wrote:
SUPER COOL! Seems like with probably just a few very minor code changes you could use half green and half red LEDs and have a tail ring that fades from green to yellow to red.

Well, now that I know that power consumption during active state can be highly reduced using the ULP oscillator (~12uA), this actually could happen! Thumbs Up

MikeMacD wrote:
Thanks! What are you using as a power source?

Hey, I think maybe you might have missed post #97 ? Is this what you’re looking for? If it’s not, just let me know.
skinny_tie
skinny_tie's picture
Offline
Last seen: 11 hours 2 min ago
Joined: 09/23/2017 - 03:14
Posts: 361
Location: Australia

I love where you’re going with your illuminated tailcap development gchart. I’ve just built one of your LVP tailcaps as my first non-emitter reflow and I’d love to build your voltage indicator design one day.

skinny_tie
skinny_tie's picture
Offline
Last seen: 11 hours 2 min ago
Joined: 09/23/2017 - 03:14
Posts: 361
Location: Australia

Cereal_killer wrote:
SUPER COOL!

Seems like with probably just a few very minor code changes you could use half green and half red LEDs and have a tail ring that fades from green to yellow to red.

Even without a code change I think it would look good with four green, two yellow, and two red LEDs.

lumenzilla
lumenzilla's picture
Offline
Last seen: 2 days 11 hours ago
Joined: 06/09/2015 - 04:18
Posts: 759
Location: DIY, Indonesia

gchart wrote:
Ok… I tested it in-flashlight. It’s a Convoy M1 with a Nanjg105c & 750 Ohm bleeder. Results seem mostly positive.

This is so sexy!

Schoki
Schoki's picture
Offline
Last seen: 2 weeks 5 days ago
Joined: 03/27/2017 - 15:34
Posts: 218
Location: Germany

Nice implementation with the MCU! Now how do you take your ADC voltage readings exactly, with the first one being wrong? I might have a simple solution, if the first value affects the average too much.

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Schoki wrote:
Nice implementation with the MCU! Now how do you take your ADC voltage readings exactly, with the first one being wrong? I might have a simple solution, if the first value affects the average too much.

It seems to be working fine at the moment, but I’d be curious to hear your ideas! Here’s an overview of the code:

Main()

  • Initialize the clock and pins
  • Run the animation
  • Shut the LEDs off and pause for 20ms to allow things to settle down
  • Run Set_Battery_Status
  • Initialize the RTC to wake us up every 60 minutes
  • Go to sleep (standby)

The RTC interrupt just clears the overflow flag and then calls Set_Battery_Status

Set_Battery_Status()

  • Turn off all the LEDs
  • Wait 10ms for things to settle down
  • Run Get_Voltage
  • Use the returned voltage to turn on desired LEDs

Get_Voltage()

  • Set Vbandgap ref to internal 2.5V
  • Set ADC ref to VDD
  • Enable the ADC, set it to 10-bit resolution
  • Get 15 ADC readings and throw them away
  • Get 8 ADC readings and add them together
  • Get the average of the 8 readings (bitshift: sum >> 3)
  • Use a calibrated formula to get the voltage. Standard formula is (1023*2.5)/reading. My formula is (2643.3/reading)+0.0267.
  • Turn off the ADC
  • Return the reading

It’s probably a bit wasteful, but I have 4K of program space to work with and I’m just turning on and off a few indicator LEDs so I wasn’t very concerned about peak efficiency.

Schoki
Schoki's picture
Offline
Last seen: 2 weeks 5 days ago
Joined: 03/27/2017 - 15:34
Posts: 218
Location: Germany

Good, I think I can contribute a bit there:
So you get 8 readings with your ADC, and then simply average them. I had these ADC reading problems with Arduinos and ATTinys as well, and I found an alternative to averaging to get better readings. I don't know if it requires less or more bytes though. Never tested it.

So the solution: get the median.
The median is the value that separates the higher half , from the lower half. To get that: Do your readings, and put them in an array. Then order them (ascending or descending, whatever you like), and take the value in the "middle" of the array. That way, a bad reading doesn't affect the value you get.
Small tip: use an array with an uneven length. If it would be an even number, you would have 2 middle values and need to take an average of those two.

I don't know how familiar you are with programming, so I'll just write it. Please let me know if you don't need code bits, it takes so long with the advanced post editor.

in C++:

//sorting array in ascending order

int i, j, temp, median;

int length = 9; //uneven is better

int array[length];

for(i=0, i<length, ++i){ //get value in array

   for(j=i+1, j<length, ++j){ //get value next to it in array

      if(array[j] < array[i]){ //if value next to it is higher, swap them

         temp = array[i];

         array[i] = array[j];

         array[j] = temp;

      }

   }

}

median = array[(length-1)/2] //for an even length it would be (array[(length-1)/2]+array[(length)/2])/2

There's even a way without using a temporary int, here's just the principle:

int x = 5;

int y = 7;

x = x + y; //x now 12

y = x - y; //y now 5

x = x - y; //x now 7, swap done

 

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Schoki wrote:
Good, I think I can contribute a bit there…

Median – nice idea! I’m actually using that same methodology for my DIY lumen tube-logger. Its a Wemos D1 Mini running Arduino hooked up to a good light sensor via I2C. Anytime there is a change, the first reading is typically off. So anytime I do a reading, I actually grab three and return the median. That’s a pretty small sample size, but it works for what I’m using it for. But yeah, median can be helpful for dealing with outliers. I could probably get away with far fewer ADC readings by using it.

Ahh, good ol’ Bubble Sort! My undergrad degree was in Computer Science, and my go-to back then was C++ (I use mostly database and web languages now).

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

I assembled another smart tailcap and put it in a S41S (stainless, not colored).

New firmware this time: when starting up, it “dials up” the battery readout and displays it for 3 seconds. Then it goes into a slow rotate animation.

Hmm… I wonder how a pseudo-random “twinkling” animation would look?

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 11 hours 4 min ago
Joined: 01/12/2013 - 14:40
Posts: 10172
Location: (469219) 2016 HO3

I always thought it might look neat to do sort of a roulette wheel animation while waiting for voltage to settle, then take a reading and slow down the animation until it stops at a point representing the current charge. After that, I figured I would have it go into a low-power beacon mode which blinks the result periodically.

That was for a RGB tailcap though. I guess on a 8-of-the-same-color design it would display based on how many LEDs are illuminated.

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

As designed, I could use multiple colors of LEDs (perhaps 4 each of 2 different colors). I’m not sure how that would work for a roulette animation, but it could be a start. And I considered having this rotating animation pause occasionally to display the battery level… not sure yet. Or perhaps just stop the animation and switch to a beacon once it hits a low-batt threshold? Dunno yet.

PS – thoughts on how to efficiently do an 8-bit pseudo-random pattern? Bitshifting a predefined pattern? Using int rand() from <stdlib.h>?

Schoki
Schoki's picture
Offline
Last seen: 2 weeks 5 days ago
Joined: 03/27/2017 - 15:34
Posts: 218
Location: Germany

Pull the code bytes out of flash with an incrementing pointer and output them. When your through, bend it back to the beginning.

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Here’s a dancing/twinkling version. After seeing it, I’m not sure if it’s my cup of tea, but it was fun to make.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 11 hours 4 min ago
Joined: 01/12/2013 - 14:40
Posts: 10172
Location: (469219) 2016 HO3
gchart wrote:
I considered having this rotating animation pause occasionally to display the battery level… not sure yet.

It should be pretty simple. The battery status is displayed based on how many LEDs are illuminated. Just rotate that same pattern. They’d still spin around, but the number lit up at any time would indicate the charge level.

gchart wrote:
PS – thoughts on how to efficiently do an 8-bit pseudo-random pattern? Bitshifting a predefined pattern? Using int rand() from <stdlib.h>?

The library rand() function would work, and you probably have plenty of space to include it. Or you could roll your own. For example, combine the contents of ROM with a random seed, and do things to make the seed more volatile. I force bits to rotate each time it’s accessed, and I also add real-world entropy to it from each ADC measurement, so it ends up being a true random instead of just pseudo-random. It’s not crypto-grade randomness, but it’s not bad for a cheap chip in a flashlight.

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Thanks TK. Nice idea on rotating the battery level.

I went ahead a precalculated a ~250 value array of values the randomly switched one bit on, then one bit off. I probably could have just called rand() from the attinys. But for now I think I’ll keep your tip in my back pocket for later.

MRsDNF
MRsDNF's picture
Offline
Last seen: 4 hours 15 min ago
Joined: 12/22/2011 - 21:18
Posts: 13226
Location: A light beam away from the missus in the land of Aus.

Very creative gc. I could not work out on the video above the dancing light how the voltage was read from the light sequence.

 

djozz quotes, "it came with chinese lettering that is chinese to me".

                      "My man mousehole needs one too"

old4570 said "I'm not an expert , so don't suffer from any such technical restrictions".

Old-Lumens. Highly admired and cherished member of Budget Light Forum. 11.5.2011 - 20.12.16. RIP.

 

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

Thanks! The voltage readout on that one happens right as it’s turning on. You’ll notice it initially ‘spin up” to a certain number of LEDs (1 thru 8) indicating voltage level. It displays that for 3 seconds, then starts a non-informative dance.

I also have it checking the voltage every couple of minutes. If it detects <3.0 volts, it’ll stop dancing and will start flashing a single LED.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 11 hours 4 min ago
Joined: 01/12/2013 - 14:40
Posts: 10172
Location: (469219) 2016 HO3

There are probably several fun things to do with an 8-pixel tail ring like that, especially if it can use the internal resistor to get more than one brightness level. Most of what comes to mind would require a relatively high frame rate though, so probably not ideal for a low-power tailcap. Perhaps it could underclock the MCU to the kHz range and/or run the WDT in sleep mode at a fairly quick rate.

I could see using it to do something similar to candle mode, except it’d also change the position, not just the brightness. Or maybe a couple simultaneous random spinners with erratic motion.

Simply spinning the battery status is probably the most useful mode though.

gchart
gchart's picture
Offline
Last seen: 3 hours 34 min ago
Joined: 03/19/2016 - 11:57
Posts: 1953
Location: Central IL

I’m currently running the main clock using the internal ultra low power oscillator, no prescaler (so 32.768 kHz). Using the real time counter interrupt to wake up as needed to move the LEDs.

I haven’t tried adding the internal pull-ups into the mix, but I bet that would work.

Also, it wouldn’t satisfy the anti-PWM crowd, but even with the main clock at 32 kHz, low-resolution PWM could be used for some fading effects. Something like a 16-level (2 kHz) or 8-level (4 kHz) PWM could work, and still be pretty low current draw. Ohh, the possibilities Smile

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 11 hours 4 min ago
Joined: 01/12/2013 - 14:40
Posts: 10172
Location: (469219) 2016 HO3
gchart wrote:
Ohh, the possibilities Smile

I know the feeling. I got a keyboard with RGB LEDs under each key, individually addressable. I was pretty excited… I had 64 pixels! So of course I immediately modified the firmware to make it run a physics simulation which responds to keypresses. It simulates the surface of a swimming pool, and each keystroke acts like a raindrop which causes waves.

While eight pixels may not be quite as flexible, it’s still plenty to have a good time. After being limited to just one pixel for so long, eight sounds like a vast playground of possibilities.

Pages