diff options
| -rwxr-xr-x | bin/level_calc.py | 60 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h | 8 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/cfg-noctigon-kr4.h | 13 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/config-default.h | 14 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/factory-reset.c | 7 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/lockout-mode.h | 5 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-ramping.c | 41 |
7 files changed, 87 insertions, 61 deletions
diff --git a/bin/level_calc.py b/bin/level_calc.py index acac332..2998b44 100755 --- a/bin/level_calc.py +++ b/bin/level_calc.py @@ -162,46 +162,54 @@ def multi_pwm(answers, channels): elif goal_lm > channel.prev_lm: # assume 7135 channels all add together if channel.type == '7135': - diff = channel.lm_max - channel.lm_min + lm_avail = channel.lm_max - channel.lm_min # assume FET channel gets higher output on its own elif channel.type == 'FET': - diff = channel.lm_max - channel.prev_lm - channel.lm_min - - needed = goal_lm - channel.prev_lm - channel.lm_min - - ceil = max_pwms[i] - ratio = needed / diff * (ceil-channel.pwm_min) - # if there's wiggle room, adjust ceiling to reduce error - #if dyn_pwm: - # this_step = max(1, math.floor(ratio)) - # next_step = this_step + 0.5 - # limit = float(this_step) / next_step * ceil - # limit = max(limit, max_pwm) - #while (ceil > limit) and ((ratio - math.floor(ratio)) > 0.1): - # ceil -= 1 - # ratio = needed / diff * (ceil-channel.pwm_min) - # max_pwms[i] = ceil - if dyn_pwm and (ceil > max_pwm): - this_step = max(1, math.floor(ratio)) + lm_avail = channel.lm_max - channel.prev_lm - channel.lm_min + + lm_needed = goal_lm - channel.prev_lm - channel.lm_min + + pwm_top = max_pwms[i] + pwm_avail = pwm_top - channel.pwm_min + pwm_needed = pwm_avail * lm_needed / lm_avail + if dyn_pwm and (pwm_top > max_pwm): + this_step = max(1, math.floor(pwm_needed)) next_step = this_step + 1 - fpart = ratio - math.floor(ratio) + fpart = pwm_needed - math.floor(pwm_needed) correction = (next_step - fpart) / next_step - ceil = int(ceil * correction) - ratio = needed / diff * (ceil-channel.pwm_min) - max_pwms[i] = ceil + pwm_top = int(pwm_avail * correction) + channel.pwm_min + pwm_avail = pwm_top - channel.pwm_min + pwm_needed = pwm_avail * lm_needed / lm_avail + max_pwms[i] = pwm_top # save the result - pwm = max(0, ratio + channel.pwm_min) + pwm = max(0, pwm_needed + channel.pwm_min) channel.modes.append(pwm) + # how close did we get? + #ptop = int(round(pwm - channel.pwm_min)) + #pbot = pwm_top - channel.pwm_min + #print('%.3f%% needed, %.3f%% actual' % ( + # 100.0 * lm_needed / lm_avail, + # 100.0 * ptop / pbot, + # )) # This channel isn't active yet, output too low else: channel.modes.append(0) # Show individual levels in detail + prev_ratios = [0.0] * len(channels) for i in range(answers.num_levels): goal_vis, goal_lm = goals[i] pwms = [] - for channel in channels: - pwms.append('%.2f/%i' % (channel.modes[i], max_pwms[i])) + for c, channel in enumerate(channels): + top = channel.modes[i] - channel.pwm_min + if top < 0: top = 0 + bot = max_pwms[i] - channel.pwm_min + ratio = 100 * (int(round(top)) / float(bot)) + top, bot = channel.modes[i], max_pwms[i] + pwms.append('%.2f/%i (%.3f%%)' % (top, bot, ratio)) + if (ratio < prev_ratios[c]) and (ratio > 0): + pwms.append('WARN') + prev_ratios[c] = ratio print('%i: visually %.2f (%.2f lm): %s' % (i+1, goal_vis, goal_lm, ', '.join(pwms))) diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h index 871a405..383a0c8 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h @@ -31,10 +31,10 @@ #undef RAMP_DISCRETE_CEIL #undef RAMP_DISCRETE_STEPS -#define RAMP_SMOOTH_FLOOR 1 // level 1 may be unreliable +#define RAMP_SMOOTH_FLOOR 11 // low levels may be unreliable #define RAMP_SMOOTH_CEIL 130 -// 10, 30, [50], 70, 90, 110, 130 (plus [150] on turbo) -#define RAMP_DISCRETE_FLOOR 10 +// 11, 30, [50], 70, 90, 110, 130 (plus [150] on turbo) +#define RAMP_DISCRETE_FLOOR 11 #define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL #define RAMP_DISCRETE_STEPS 7 @@ -54,7 +54,7 @@ // jump start a bit higher than base driver #undef JUMP_START_MOON -#define JUMP_START_MOON 25 +#define JUMP_START_MOON 31 // stop panicking at ~1300 lm #undef THERM_FASTER_LEVEL diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index f5625c7..d584445 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -43,10 +43,10 @@ #define HALFSPEED_LEVEL 12 #define QUARTERSPEED_LEVEL 4 -#define RAMP_SMOOTH_FLOOR 3 // level 1 may be unreliable +#define RAMP_SMOOTH_FLOOR 11 // low levels may be unreliable #define RAMP_SMOOTH_CEIL 130 -// 10 30 [50] 70 90 110 [130] -#define RAMP_DISCRETE_FLOOR 10 +// 11 30 [50] 70 90 110 [130] +#define RAMP_DISCRETE_FLOOR 11 #define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL #define RAMP_DISCRETE_STEPS 7 @@ -58,8 +58,9 @@ // stop panicking at ~1300 lm #define THERM_FASTER_LEVEL 120 #define MIN_THERM_STEPDOWN 66 // must be > end of dynamic PWM range -#define THERM_NEXT_WARNING_THRESHOLD 16 // accumulate less error before adjusting -#define THERM_RESPONSE_MAGNITUDE 128 // bigger adjustments +// no longer needed, after switching to dynamic PWM +//#define THERM_NEXT_WARNING_THRESHOLD 16 // accumulate less error before adjusting +//#define THERM_RESPONSE_MAGNITUDE 128 // bigger adjustments // slow down party strobe; this driver can't pulse for 1ms or less // (only needed on no-FET build) @@ -68,7 +69,7 @@ #define THERM_CAL_OFFSET 5 // the power regulator is a bit slow, so push it harder for a quick response from off -#define JUMP_START_MOON 25 +#define JUMP_START_MOON 26 #define BLINK_BRIGHTNESS DEFAULT_LEVEL #define BLINK_ONCE_TIME 12 diff --git a/spaghetti-monster/anduril/config-default.h b/spaghetti-monster/anduril/config-default.h index 31fcbf4..a50be5d 100644 --- a/spaghetti-monster/anduril/config-default.h +++ b/spaghetti-monster/anduril/config-default.h @@ -37,7 +37,19 @@ // overheat protection #define USE_THERMAL_REGULATION #define DEFAULT_THERM_CEIL 45 // try not to get hotter than this (in C) - +// Comment out to disable automatic calibration on factory reset +// - If so, be sure to set THERM_CAL_OFFSET to the correct calibration offset +// - Calibration can still be overridden in temperature check mode +// Or uncomment to use the default auto-calibrate on factory reset +// +// To determine THERM_CAL_OFFSET, comment out USE_THERM_AUTOCALIBRATE to +// disable auto-calibration, compile and flash, let flashlight rest at a known +// temperature, then enter temp check mode (do NOT enter calibration mode). +// +// THERM_CAL_OFFSET = known_temperature - temp_check_blinks + THERM_CAL_OFFSET +// +// (include THERM_CAL_OFFSET in sum as it might already be a non-zero number) +#define USE_THERM_AUTOCALIBRATE // Include a simplified UI for non-enthusiasts? #define USE_SIMPLE_UI diff --git a/spaghetti-monster/anduril/factory-reset.c b/spaghetti-monster/anduril/factory-reset.c index f05b5eb..ecb4cc2 100644 --- a/spaghetti-monster/anduril/factory-reset.c +++ b/spaghetti-monster/anduril/factory-reset.c @@ -43,13 +43,12 @@ void factory_reset() { } // explode, if button pressed long enough if (reset) { - #ifdef USE_THERMAL_REGULATION - #ifdef AVRXMEGA3 // AVR 1-Series has factory calibrated thermal sensor, remove the offset + // AVR 1-Series has factory calibrated thermal sensor, always remove the offset on reset + #if defined(USE_THERMAL_REGULATION) && defined(AVRXMEGA3) thermal_config_save(1,temperature - therm_cal_offset); // this will cancel out the offset - #else + #elif defined(USE_THERMAL_REGULATION) && defined(USE_THERM_AUTOCALIBRATE) // auto-calibrate temperature... assume current temperature is 21 C thermal_config_save(1, 21); - #endif // AVRXMEGA3 #endif // save all settings to eeprom // (assuming they're all at default because we haven't loaded them yet) diff --git a/spaghetti-monster/anduril/lockout-mode.h b/spaghetti-monster/anduril/lockout-mode.h index 021d34a..1c9c081 100644 --- a/spaghetti-monster/anduril/lockout-mode.h +++ b/spaghetti-monster/anduril/lockout-mode.h @@ -24,7 +24,10 @@ uint8_t lockout_state(Event event, uint16_t arg); #ifdef USE_AUTOLOCK -uint8_t autolock_time = 0; +#ifndef DEFAULT_AUTOLOCK_TIME +#define DEFAULT_AUTOLOCK_TIME 0 // autolock time in minutes, 0 = disabled +#endif +uint8_t autolock_time = DEFAULT_AUTOLOCK_TIME; uint8_t autolock_config_state(Event event, uint16_t arg); #endif diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 503f90f..1a08149 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -153,30 +153,33 @@ void set_level(uint8_t level) { #endif // ifdef USE_TINT_RAMPING #ifdef USE_DYN_PWM + uint16_t top = PWM_GET(pwm_tops, level); + #ifdef PWM1_CNT + // wait to ensure compare match won't be missed + // (causes visible flickering when missed, because the counter + // goes all the way to 65535 before returning) + // (see attiny1634 reference manual page 103 for a warning about + // the timing of changing the TOP value (section 12.8.4)) + // to be safe, allow at least 64 cycles to update TOP + while(PWM1_CNT > (top - 64)) {} + #endif // pulse frequency modulation, a.k.a. dynamic PWM - PWM1_TOP = PWM_GET(pwm_tops, level); + PWM1_TOP = top; + + // repeat for other channels if necessary #ifdef PMW2_TOP - PWM2_TOP = PWM_GET(pwm_tops, level); + #ifdef PWM2_CNT + while(PWM2_CNT > (top - 64)) {} + #endif + PWM2_TOP = top; #endif #ifdef PMW3_TOP - PWM3_TOP = PWM_GET(pwm_tops, level); - #endif - - // reset the phase, to avoid random long pulses - // see attiny1634 reference manual page 103 for a warning about - // the timing of changing the TOP value (section 12.8.4) - // (we don't care about being phase-correct, so the brute-force - // approach can be used to reset it here) - #ifdef PWM1_CNT - PWM1_CNT = 0; - #endif - #ifdef PWM2_CNT - PWM2_CNT = 0; - #endif - #ifdef PWM3_CNT - PWM3_CNT = 0; + #ifdef PWM3_CNT + while(PWM3_CNT > (top - 64)) {} + #endif + PWM3_TOP = top; #endif - #endif + #endif // ifdef USE_DYN_PWM } #endif // ifdef OVERRIDE_SET_LEVEL #ifdef USE_DYNAMIC_UNDERCLOCKING |
