Attiny25/45/85 FW Development Thread

I think I figured out internal Vcc measurement (so we can remove R1/R2).

Its all in 17.13.1 (page 134) of the datasheet.

The only required ADC-configuration change is to set the ADMUX register to use Vcc as reference voltage. (Note this configuration will give a 10-bit result, to be read from the ADC register.):

ADMUX = b00001100;

If we want to read internal temperature, ADMUX need to be set back to read ADC4 with Vbg as reference:

ADMUX = b10001111;

…and we then alternate between the two configurations with a small time delay after each change. Possibly we also need to read the ADC twice each time, to get more accurate results.

To figure out the ADC result for Vcc:

adc_result = ADC;    //16-bit integer

where adc_result = (Vbg / Vcc) * 1024;
= Vbg / (Vbat - D1) * 1024;

where Vbg = 1.1 V
and D1 = drop over Schottky = ~0.25 V

So adc_result = 1.1 * 1024 / (Vbat - 0.25)

The typical lookup table we use will look like this for Vbat:

4.2 V = 285
4.1 V = 293
.
.
.
2.5 V = 501

Note lower Vbat gives higher results (Vbg becomes larger as a percentage of Vcc). This would also be an opportunity to finally upgrade to 10-bit ADC operation.

DEL, has anybody told you lately that we really appreciate you here? Thanks for working on this stuff for us. :smiley:

With all these driver improvements going on, as well as Tom E and ToyKeeper kicking out newer and better firmware so often, it’s a good time to be a BLFer!

DEL - does this match what Halo... posted in post #731: https://budgetlightforum.com/t/-/34900/731 ?

DEL - is very much appreciated!!

Very exciting. Once we get this into common firmwares I can drop two 0805 components off my boards (so it will be much easier to fit on the little ones, like the glorious X2R) and we get an extra pin available, so triple channel + indicator LED for NARSIL, or maybe some dual-eswitch lights if the host fits, or who knows what else

Just a reminder: internal Vcc measurement doesn’t work with zenermods.

Ouch! Didn't realize that, makes sense, and am sure was mentioned, and forgotten by me . Can we assume same for LDO, because it's doing the same thing, regulating the voltage coming in to the MCU?

Could we take a voltage reading on the same pin but compare it to the internal reference? Or is it still limited to ~6v max no matter the input pin?

That is what we are doing currently. But once you exceed 1.1 V the reading is saturated. Therefore R1/R2.

There are other options: a 2.56 V reference, external reference, or Vcc as reference. None useful to us unfortunately.

Very much the same thing.

long readVcc() {
ADMUX = _BV(MUX3) | _BV(MUX2);     // Set reference to Vcc and measurement to internal 1.1V bandgap
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first, it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<8) | low;
//Note: might need to discard first result
result = 1125300L / result; // Calculate Vcc in millivolts; 1125300 = 1.1*1023*1000
}

‘ADMUX = _BV (MUX3) | _BV (MUX2);’ is equivalent to ‘ADMUX = 0b00001100;’.

Then there is a delay for Vref to settle. I would do this differently to not hold the program.

‘low = ….’ together with ‘high =…’. and ‘result = …’ can be simplified to simply ‘result = ADC;’.

Halo is calculating the voltage in mV, which is also a valid approach - removes the need for a lookup table.
The D1 drop has to be added to this calculation to get the cell voltage. EDIT: and it should be 1024 in the formula, not 1023.

And yes, unfortunately not useful for zener or LDO fed MCUs.

Not lately :D, but it is people like Tom and TK that do all the heavy lifting!

Yes, it’s worth saying again, Tom and TK are very much appreciated as well!

Indeed, if not for all the hard work and time of these people flashlights would still have 5 modes with blinky being a non-option. lol

Yeah, but don’t talk too bad about blinkies… TK loves them!

Thanx!

TK likes her biking blinkies - does a lot of night time biking, I'm assuming.

Proof of concept, if anyone wants to try it:

tiny25/45/85 Vcc and temperature reading

As configured the firmware is for a FET+1 driver.
No memory, starts up in medium mode, one click to low, another to moon.
Next mode after that is cell voltage flash-out.
And after that is the MCU temperature flash-out.
Then a bunch of blinkies to be ignored.
There is a pseudo ‘double-click’ from off to get to DD mode.

The new ADC stuff is mainly inside the ADC interrupt routine spanning lines 159-183.

Mind the fuses, as programmed it is meant for a 1 MHz clock:

 * Fuses:
 *      Low:  0x62      (8 MHz clock, 8* divider, 14 CK + 64 ms startup)
 *      High: 0xdf      (no BOD, SPI enabled)
 *      Ext:  0xff      (self prog disabled)

avrdude -c usbasp -p t25 -u -B 10 -Uflash:w:???.hex -Ulfuse:w:0x62:m -Uhfuse:w:0xdf:m -Uefuse:w:0xff:m

Dang, looks pretty good! Like the ADC service interrupt - don't think anyone else has done that, and like the round robin scheduling - simple, but should work fine.

Also like the critical level shutdown - can't recall if other clicky firmware does that, maybe... Don't think anyone else shut down ADC - I added that after Halo brought it up, and save some mA.

I know we had a reason to try 1 Mhz -- think to save power. I need the 16 ms ISR right now because ramping is based on that. I've run a std Tiny85 (no V) down to 2.3V without a hitch, though the LED was just bout glowing, had to cup my hands over it to see it was ON.

You got a lot of stuff in there, actually... All in 1574 bytes. Really nice job!!!

Update: Just compiled/built it - I got 1538 bytes -- even better! Compiler says no errors, so must be perfect!

K, got a Q: how good is the temperature reporting? Some +/- issue? Thought the internal temp monitor was pretty rough - need calibration?

Thanks Tom :slight_smile: . I used to run most of it on a 13A. The 25 allows luxuries like the 16-bit operations.

There are probably a few things in there that you will not agree with, like the 2 kHz PWM. That is actually my main reason for the 8/8 MHz clock. I also tend to stick with the default MCU clock to get more accurate timing.

You can use the ADC ISR as is without affecting your WDT. I am using the WDT only to periodically trigger the ADC. You can do the same. Should work at 16 ms. If not, just arm the ADC every 4 ticks.

The temperature reading is within 5 degrees or so. One sample here reads 2 degrees low, another 3 degrees low and yet another also 3 degrees low. This is at room temperature. The datasheet recommends at least a zero offset calibration. Treating the raw value as Kelvin and subtracting 273 would make sense, and bring the values in closer, but the datasheet specifies 300 = 25 C for some reason.

Hhmm. 5C is bout 9F. 2-3C off isn't that bad I'd think, for our use. Think the bigger problem is how the MCU temp varies with actual LED and host/body temps, and related to that, is how dynamic the adjustments are done - can't be too reactive, but have to be quick enough so the temp of the LED/host don't get out of control. I'm sure the overall design has a lot to do with it - LED's, amps, thermal mgt, host, etc.

I finally got the latest Narsil updated in my SkilHunt H15 - it's really nice to have the ramping in a pocket flooder. I know there's been excitement wit the new HaikeLite's, and talks bout the UI - but quick access from OFF to either last mode, moon mode (lowest mode), and turbo is bout as good as it gets.

  • click to last mode
  • click&hold to moon
  • double-click to max/turbo

Apart from the thermal delay, there is also the resolution of the signal to consider.

I tried a PID (actually PI) loop. It was relatively easy, even being limited to integer arithmetic. But we are limited to a resolution of 1 degC. And P needs to be in the order of ~10 to be of any use. Having a 1 degC loop error and the loop output then adjusting by P x Error (PWM moves up/down in steps of 10) was irritating. Either the loop input, output, or the calculated error, will need to be slow-ramped. Apart from the limitations imposed by integer arithmetic, there is also the artificial impact this ramping will have on the loop itself.

Hint for anyone that wants to try this, you absolutely need to simulate the ‘process’. Even something simple in a spreadsheet will help.

++1
I find I have been replacing some really good drivers in favor of your firmware and the options you mention. When using a light a lot, anything else is inefficient and enjoying!