On a FET board, it’s difficult to get a true moon mode. In general, a value of PWM=1 will produce anything from 1 to 15 lumens depending on the cell and emitter(s) used. You can go lower by using fast PWM=0, but it’s incredibly voltage-sensitive and I’ve seen it put out as much as 4 lumens on a full cell (and down to 0.001 on a low cell, same light). You’ll get somewhat more stable output with phase-correct PWM, but the lowest level on that is 1 and it’ll probably be too bright for moon.
I tried using fast PWM=0 plus dynamic voltage-determined PFM (pulse frequency modulation) to get a better FET-only moon mode, but even that merely reduced the problem rather than really fixing it. You’re welcome to try it if you like though; the code is in ToyKeeper/cypreus/cypreus.c .
This is one of the reasons people use FET+1 drivers instead. The +1 gives you a single 7135 chip which can drive all the modes under about 140 lumens. It should produce a nice moon mode, plus stable current-regulated “low” and “medium” modes. It can also help reduce output sag on modes above that, and make the PWM even less visible.
I haven’t looked at that code for ages so I can’t tell you exactly which lines, but commenting out ADC_LOW is not the only thing you have to do.
Later on in the code, the voltage reading routine compares the read voltage to ADC_LOW. As you’ve commented out the ADC_LOW definition the compiler doesn’t know what to compare it to. Setting ADC_LOW to 0 or at least something lower than ADC_CRIT might not be the prettiest method, but it’s the easiest and should work.
I still had Star 1.1 on my hard disk so I checked. If the low voltage check passes, the critical volt check will not be executed… So you can stop your test, it will not work. Gimme a sec and I’ll see if there is a simple way of doing it…
The version of Star I have doesn’t have ALT_PWM level, so I’m sure we are not looking at the same code.
However, you are right. I forgot about that part. As it is now it goes to step down on critical, then shuts off. You want it to shut off straight away.
So, another quick fix without extensive editing… Keep the last change and then change:
if (mode_idx == 0 && ALT_PWM_LVL <= modes[mode_idx])
to:
if (1)
Not a pretty solution, but requires minimal editing… unless I’ve missed something else…
Comment out “#define ADC_LOW” and replace the voltage-mon section with this one:
EDIT: Too late :~ , but its a cleaner soultion
#ifdef VOLTAGE_MON
#ifdef ADC_LOW
if (low_voltage(ADC_LOW)) {
// We need to go to a lower level
if (mode_idx == 0 && ALT_PWM_LVL <= modes[mode_idx]) {
// Can't go any lower than the lowest mode
// Wait until we hit the critical level before flashing 10 times and turning off
#endif
while (!low_voltage(ADC_CRIT));
i = 0;
while (i++<10) {
set_output(0);
_delay_ms(250);
set_output(modes[0]);
_delay_ms(500);
}
// Turn off the light
set_output(0);
// Disable WDT so it doesn't wake us up
WDT_off();
// Power down as many components as possible
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
#ifdef ADC_LOW
} else {
// Flash 3 times before lowering
hold_pwm = ALT_PWM_LVL;
i = 0;
while (i++<3) {
set_output(0);
_delay_ms(250);
set_output(hold_pwm);
_delay_ms(500);
}
// Lower the mode by half, but don't go below lowest level
if ((ALT_PWM_LVL >> 1) < modes[0]) {
set_output(modes[0]);
mode_idx = 0;
} else {
set_output(ALT_PWM_LVL >> 1);
}
// See if we should change the current mode level if we've gone under the current mode.
if (ALT_PWM_LVL < modes[mode_idx]) {
// Lower our recorded mode
mode_idx--;
}
}
// Wait 3 seconds before lowering the level again
_delay_ms(3000);
}
#endif
#endif