Whereas a reverse-clicky can be hard to learn for a “muggle,” this should be easier because the momentary switch is just 1-position. Clicking always advances modes, and holding turns it off no matter how long or short you hold it.
having hard time blinking out some numbers (i.e. to blink out results of ADC or voltage or some state variables).
The blink out function works fine, but for some reason, invoking it in while(1) loop in main function causes big lag and sometimes unresponsiveness. I tried to put in inside WDT_off / WDT_on, but with similar unpredictable results.
Has anybody implemented this with success?
This is how I implemented the blinking function:
void blink_single_digit(uint8_t digit)
{
if (digit==0) digit=11;
uint8_t i=0;
PWM_LVL=0;
ALT_PWM_LVL=0;
do
{
ALT_PWM_LVL=0;
_delay_ms(400);
ALT_PWM_LVL=10;
_delay_ms(400);
i;
}
while (i<digit);
}
This is where and how I invoke it:
while(1)
{
// We will never leave this loop. The WDT will interrupt to check for switch presses and
// will change the mode if needed. If this loop detects that the mode has changed, run the
// logic for that mode while continuing to check for a mode change.
This really is very similar to the Baton interface (which already has lock-out implemented), except with long and short presses sort of reversed. Baton does the following:
From off:
Short press: go to last-used mode
Double press: go to turbo
Long press: go to moon mode
Longer press: soft lock-out
While on:
Short press: turn off
Double press: not yet implemented (turns off then on)
Long press: next mode (keep holding to keep cycling, skips moon mode and “off” mode)
While locked:
Press for 3 seconds to unlock
The default long press is 1/3rd second, but it’s easily tweakable in a #define along with several other options.
I haven’t found a place to put a battery check mode yet, but it does at least support realtime voltage indicator lights. I’m thinking perhaps the lockout mode could be used for battery check if the use sets a #define, and the double-press while on should probably go to another blinky mode like beacon or strobe.
What you’re trying to do is basically threading or other parallel programming. This is not going to be easy to do on such a minimal processor.
If it’s in the main loop, that entire loop will be blocked until the blinking readout is done. If you do it in an interrupt handler, you either have to disable interrupts until you’re done (and ignore events) or risk re-entering the handler while it’s already running.
You could do it with threads, but I doubt there’s a preemptive threading library for attiny (and if there is, it probably wouldn’t fit). So, your best option is probably to implement your own cooperative threading or to work both threads into a single logic stream in the main loop. Perhaps build a task queue which gets processed in the main loop but can be interrupted by other events, and the blink digit function would simply add tasks to the queue?
In any case, what I’m saying is it’s probably going to be a bit of a pain since the MCU is designed for only specific types of parallelism and I don’t thank that’s one of them.
I actually tried baton on my test rig, and it was close to what I wanted, but i thought it would be easier to use plain STAR as my stepping point.
The main things I didn’t like:
- I don’t like to use a double click as a commonly used function (just preference)
I wanted the cycle to always start at moon, not the last mode.
I do like how you’ve implemented the lockout, but I’d rather have the unlock function to be a double click (just because that’s less likely to happen in a pocket than a long press is)
Is it possible to have a long press from off to lockout, and a double click to unlock to moon?
The reason it works that way is simply because I was copying an existing interface. It doesn’t have to stay that way.
I think a double click could be used to unlock; I just haven’t ever tried it.
The memory could also be removed, which would simplify the interface. Or you could, you know, start with STAR-momentary as a base instead… which already works that way.
I probably won’t have time to mess with it for a while, but I wanted to make sure you were aware of it in case it might be useful.
I have the UI in post #913 working now, I’ll just have to play with the lockout function (probably start by copying from Baton) to get it to my liking.
I made a small add-on to star_momentary which dynamically changes the pwm level of the lowest moon mode depending on voltage.
Why?
Because I wanted a lowest moon mode (which is Phase corrected PWM level 2 when using 2 channel / a single 7135), and it doesn’t emit any light below cca 3.1V.
So I implemented a routine to up it to level 3 if the voltage goes below that level, so your light can always be able to work in the lowest available moon mode.
I did something similar in my cypreus firmware, where “moon” means “fast PWM=0”. It changes the PWM speed according to voltage, so that the moon mode will be less voltage-sensitive. At 4.2V it’ll run at the usual 19 kHz, but at 3.5V it pulses at 2.4 MHz. In-between it adjusts smoothly.
Below 3.5V it mostly just gets too dim to see, but that’s okay because the high-amperage cells I’m using are basically empty at that level anyway so I would need to change the battery.
If you find that changing the PWM level is too big of a jump, you could use PFM to adjust it more smoothly. However, this is incompatible with dual PWM so it won’t work on a driver such as the “moonlight special” with two independent PWM channels.