Attiny25/45/85 FW Development Thread

Anyway, I'm really not that worried about that, was just trying to point out several nuiances that matter but the two adc setups is a bigger one to watch out for.

What I care more right now, is does anyone know what happens to the RAM on these things when they're unpowered? Does it decay to all zeros? To all ones? Or to something random? If it's either of the first two, I can take advatage of it. If it's the last, I probably better switch to eeprom. Mostly I don't actually need memory rentention during power off. I just need retention when restarting the program using a variable that won't get reinitialized. But I have no way to tell the difference between a restart and a cold start other than this variable, and in the cold start the uninitialized variable would be corrupt. I'll probably just switch to eeprom. I'm not sure this wear levelling is really needed anyway. Is anyone planning to change modes on their light 100,000 times? I might be able to find a way to squeeze it into the mode save wear levelling as the second byte in the train. It needs a few bytes of code though and, well, I have a few left.

hmm.. another way to do this is to turn main into a subroutine fake_main, and have real main just call it. The global variable are initialized in main, but I jump to fake_main to bypass initialization. I'd have to figure out how to reliable get the jump address for fake_main. It shouldn't be a function call because I'm inside an interrupt (or two) and want to clear the stack. Hmm maybe I could just clear the stack at the start of fake main. Very hackish, but it's all a bit hackish.

My friend, you are arguing in a circle. The different channels share the load however all 7135s + %1 of the fet is still brighter(unmeasurable but…) than all 7135s on there own. Whatever percent load you add from the fet will cause some voltage sag, but the 7135s don’t care, they dump off extra voltage anyway. Less voltage to dump off even makes them more effitient. Correct? I should keep quiet cause you are much smarter than I. So just take my comments as trying to help.

It doesn't matter because in the end you're going to adjust the correction factor from experience. There are just things easier about doing it one way, and other things a little easier about the other. As far as the 1% difference in having both channels, both ways reach that at 100%.

This is all right. A line is a line is a line. ONe just has to figure out how to do it in the fewest bytes, make it most comfortable for mode definitions, and avoid things like overflow errors. Starting from the bottom (which is also what I did) has a physical significance because the bottom battery voltage is the real equivilent vf you're targetting. Starting from the bottom does make overflow a little easier too. If your slopes are right nothing should ever PWM to zero (because that's just the all7135 mode and you should have just been using that anyway then). However starting from the top the math will try to produce more than 100% at some point as your voltage drops too low and you'll have to catch the overflow in the calculation, or just know where the bottom is and put a conditional to catch it. But once you know where to put that, you've already found the bottom anyway. No matter what, you need to know where the bottom is. And might as well approach it with that idea so you can just get to it and figure out if your battery even has enough juice to hit the mode.

That's why I just went ahead and defined modes by bottom voltage. You can still use a ramp table like we have. You'll just have to calculate the bottom voltage from there.

While you are correct in your technical thinking, I am a much more practical guy. If all the 7135’s are on, the total current through the light with any PWM to the FET will be higher then the combined 7135’s. Will the efficiency be effected some? Sure but it will still have more current and be brighter with any added FET PWM on top of the 7135’s.

The tiny amount of technical variance that you are describing will not even remotely be noticeable to the human eye, as such I am not worried about it.

This setup will not be anything close to perfect anyways, the idea is to simply improve things better then they are now and see how it plays out. What we learn from this can be applied to a future tiny85 version of the firmware where it can be expanded to take into account the tiny things you are mentioning bringing up.

At least that is how I see it.

Wow, what I'm finding is this ram lasts an enormously long time with 10uF cap in place. So far it's remembered for about 3 or for minutes. Haven't tested longer. Anyone interested in a memory mode that remembers for say half an hour but eventually resets to default? That would actually fit my usages. Would have to tackle this eventual corruption issue though. Maybe set four or 5 bytes to 170 (10101010) and check all 5 to verify non corrupt state. It's an idea for my restart problem too though.

I'm not worried about any tiny technical variance. It will quite drastically impact the correct slope to use. But anyway, the slope will get set by testing. The difference in those slopes affects how easily you cna define regulation modes for all levels vs just the top ones. And more importantly to you, it means that determination depends on how many 7135s you have. That's all. The variation from whatever wrongly shaped line we use probably isn't a big deal since it will be wrongly shaped regardless.

Bottom line, you're going to need different calibration constants for different numbers of 7135s, especially switching between tripple's and FET+1's. That's a huge effect, not tiny. If you PWM it all together there's less impact from that and you'll get regulated modes that work pretty well on all drivers. The flip side though is your mode orders might get out of whack when switching drivers. So either way, you need some setting changes. Just different ways to skin the cat.

Yeah, I just got 20 minutes of RAM memory. Of course in reality there will be 40uF not 10 but the power will get run down to 1.8V or so by OTSM. so who knows how long it will last if at all. It has to just accidentally work out to 20 to 60 minutes probably to be useful. For temporary memory less or more isn't useful. It's like OTC all over again, on longer scales. Will depend on every resistor in the driver. Too much nuisance.

Of course I'm being abusive with this program restart. Nobody encourages programming this way. The kosher way to do things is to set flags and unroll out of the (nested) interrupts back into the main program. Then I'd need to add checks to short circuit the delay functions to bypass all the strobbing and menus and whatever going on, and then break out of the loop at the end and restart initialization from there, keeping the variables I want. It's still a possibility but I don't like it. There are many places where variables between user click and true restart will get messed with where they just weren't designed to be messed with because a full reset was anticipated. It requires really rethinking the whole program, so I continue with the hacks.

RAM corruption test.

So I got my answer on this particular byte of ram in this chip. If loaded with 10101010 it always corrupts to 00011001 or 25 after shorting the caps (no, not 255). Slightly surprising that it's stable, but still mostly useless. I don't like betting that the byte I care about isn't the first one to get a bad bit either, so checking other bytes for corruption probably isn't a solution. It will have to be one of the other three solutions to carry data back to the start (post init jump, eeprom, or interrupt unrolling).

Now that I'm staring at assymbly more anyway, I'm a bit less ethusiastic. Below is a do-nothing interrupt handler (intentionally does nothing), in C it was empty:

ISR(WDT_vect){
00000197 PUSH R1 Push register on stack
00000198 PUSH R0 Push register on stack
00000199 IN R0,0x3F In from I/O location
0000019A PUSH R0 Push register on stack
0000019B CLR R1 Clear Register
0000019C POP R0 Pop register from stack
0000019D OUT 0x3F,R0 Out to I/O location
0000019E POP R0 Pop register from stack
0000019F POP R1 Pop register from stack
000001A0 RETI Interrupt return

Well, yes, that does absolutely nothing, except move some bytes there and here, and back there again. It seems like probably standard ISR setup to save things (working registers and status register) to stack and clear register (R1 anyway) so you can do something, and then pull the stuff back off the stack again at the end to put it back as it was. But I'd kind of think since nothing is being done, it should be kind of smart enough to actually do nothing. It sure seems to me like the only instruction needed here is "RETI". Looks to me like a bit of inline assymbly could save some more bytes. I wasn't really looking for this. Just ran into it trying to understand something.

Ahh, more details here:

http://www.avrfreaks.net/forum/why-code-empty-interrupt-routine

The first answer isn't helpful at all but it gets better.

I am looking at things from the big picture, what you actually see with your eyes point of view.

From this point of view it is a tiny effect that will be all but unnoticeable to the human eye. In fact I would venture to say it would be totally unnoticeable as any mode that would use software regulation would be after the 7135’s are already on and at that point the human eye just can’t make out rather large differences in output.

When the difference from the 7135’s to turbo is ~800 lumens to ~1100 lumens and you have to got back and forth a few times to make sure turbo was actually working, I am simply not worried about something that would make a fraction of that amount of difference in output.

As far as needing septate calibrations for different numbers of 7135’s, I actually kind of doubt this will be the case, I don’t change the firmware at all for the different 7135’s levels I use right now. at least not for a change of 1-2 7135’s. The 22mm drivers have 9 of them and the 17mm have 7. Both work perfectly fine with the default firmware needing no changes. The LED used plays the much larger role from my experience.

Now triples might need a different table but even this I think will work fine with the same basic slope, sure it will not work the same but once you get into triple lumen levels even larger differences in output are unnoticeable to the human eye. 3000 vs 3800 lumens in a triple is hardly noticeable if the beam profile is the same.

Yeah, 7 vs 9 won't be a big deal. 4 vs 9 though, yeah, maybe. 1 vs 9 certainly. Anyway, perception and usefulness are not the same thing. More light is more useful, especially in traffic.

Anyway. Restart works. I can distinguish restarts from cold starts now without corruption concers, without rewriting the whole program or using eeprom, just some stack hacking. I also realized I was being silly about detecting memmory decay. It's not like checksums or redundancy are a new concept. Just write a byte 4 times and make sure they're all the same. That's not what I did here though in the end, but it could be done to make the existing OTC-less fastpresses work better or to have mid-term memory/timing over periods of say of an hour, which actually looks possible.

You make a habit of blinding drivers in traffic?

I think you're looking for the other light forum. Man, you can get banned there for even discussing any kind of non-DOT approved illumination.

At some point I started getting wakes from real non-simulate restarts. Just 128+ ms. It doesn't sound like much but basically I think initial sleep detection and shutdown eats through a ten'er. Every 10uF from there should add about 1.5s. I'm at 4.2V but I'm also at 2.7V cuttoff, so not so different from 3V and 1.8V cuttoff. I'll see how many caps I can balance on top of each other.

LOL, well I referring to your earlier post:

I can’t come up with a situation where more lumens in traffic is a concern? I tend to try to stay out of the street, particularly at night. But thats just me. :stuck_out_tongue:

On a bicycle at high speed, you need much more "microsopic" vision of the road surface than you do in a car. Ruts will kill you. Not everything has to point up. But other lights around (from traffic etc) do reduce your contrast. It's not perceived brightness that matters. It's actual brightness that determines how far down the road you can see well. I don't think I was the only one saying this in the modes group discussion. Anyway, my single 18650 lights, don't put out 3800 lumens.

What you want on a bike light is to be able to set it to a fixed brightness, have it stay there, and select the appropriate such brightness based on the runtime you need to get.

oh, and that power off wasn't quite real.. I shorted c1. I mean that does shut power off, but it shuts it of FAST. So it's still kind of cheating.

So 4 s 2s (didn't reset the counter, oops) with another 20uF added , my prediction wasn't that far off. But actually that was with 1.8V cuttoff (always was)..1.25s 0.75 at 3.1V on this chip though. Many more ifs, ands, and buts compared to a final light still some good, some bad. One of the big ifs is that the ADC wasn't on during power off detection and power off is clearly about 10uF worth of the drain. All this matches up reasonably well (still true after correction, was a bit high, is now a bit low) with the current measurements I made before. I still think this is probably the cause of Mike C's observations about the ADC being so important.

I set the main loop to only turn on the adc before taking readings, added idle sleep to the delay function, sped up the ADC, and added a 16ms delay (sleep) in the main loop. This should keep power-off detection drain under control hopefully.