aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorSelene ToyKeeper2024-03-26 03:41:17 -0600
committerSelene ToyKeeper2024-03-26 03:41:17 -0600
commit35b5c42f8996167248b7e6d2e4053f6bbef1505c (patch)
tree7b852c3965c277e749285ceeaccd043730647210 /hw
parentdammit, got alkaline detection half working and then my flashing adapter died (diff)
downloadanduril-35b5c42f8996167248b7e6d2e4053f6bbef1505c.tar.gz
anduril-35b5c42f8996167248b7e6d2e4053f6bbef1505c.tar.bz2
anduril-35b5c42f8996167248b7e6d2e4053f6bbef1505c.zip
d3aa: got weak battery detection actually working,
and not letting the magic smoke out of updi adapters any more (probably) The alkaline detection might be a little too lenient though; it could potentially fail to activate limits when the cell is completely full or stronger than an average alkaline. One of my test cells measured at 72 / 75, so if it was just a little stronger it'd pass... but most alkalines I tried were in the 40 to 60 range and failed easily. OTOH, if I make it easier to fail, it's likely to trip on normal li-ion cells, and I don't want that. So as a future enhancement idea, maybe it should have a smaller sag threshold for AA and a larger threshold for li-ion. That would reduce false negatives for AA, while still preventing false positives for li-ion.
Diffstat (limited to 'hw')
-rw-r--r--hw/hank/emisar-d3aa/hwdef.c84
-rw-r--r--hw/hank/emisar-d3aa/hwdef.h7
2 files changed, 53 insertions, 38 deletions
diff --git a/hw/hank/emisar-d3aa/hwdef.c b/hw/hank/emisar-d3aa/hwdef.c
index f6cf94e..d6cb2fd 100644
--- a/hw/hank/emisar-d3aa/hwdef.c
+++ b/hw/hank/emisar-d3aa/hwdef.c
@@ -114,16 +114,11 @@ uint8_t voltage_raw2cooked(uint16_t measurement) {
#ifdef USE_WEAK_BATTERY_PROTECTION
uint8_t quick_volt_measurement() {
- // take the average of a few samples
- // (assumes the ADC is in voltage mode and running continuously)
- uint16_t total = 0;
- for (uint8_t i=0; i<8; i++) {
- uint16_t m = adc_raw[0];
- total += voltage_raw2cooked(m);
- delay_zero();
- }
- uint8_t v = total / 8;
- return v;
+ // wait for next hardware measurement
+ irq_adc = 0;
+ while (! irq_adc) {}
+ uint16_t m = adc_raw[0];
+ return voltage_raw2cooked(m);
}
void detect_weak_battery() {
@@ -133,44 +128,65 @@ void detect_weak_battery() {
// - determine how much to limit power
// - blink to indicate weak battery mode, if active
+ ramp_level_hard_limit = 0;
+
uint16_t resting, loaded;
+ // baseline unloaded measurement
set_level(0);
+ for (uint8_t i=0; i<32; i++) { delay_zero(); } // wait about 10ms
+ //resting = voltage_raw2cooked(adc_smooth[0]); // probably not settled yet
resting = quick_volt_measurement();
- set_level(WEAK_BATTERY_CHECK_LEVEL);
- loaded = quick_volt_measurement();
+ // progressively turn up the power until sag threshold is hit,
+ // or critical voltage, or max testing level is reached
+ for (uint8_t l=1; l<WEAK_BATTERY_TEST_MAX_LEVEL; l++) {
+ set_level(l);
+ loaded = quick_volt_measurement();
+ int16_t sag = resting - loaded;
+ if (
+ // AA/NiMH critical voltage
+ (loaded <= DUAL_VOLTAGE_LOW_LOW) ||
+ // weak battery chemistry, can't handle much power
+ (sag > WEAK_BATTERY_SAG_THRESHOLD) ||
+ // Li-ion critical voltage
+ ((resting > VOLTAGE_LOW) && (loaded < VOLTAGE_LOW))
+ ) {
+ ramp_level_hard_limit = l;
+ break;
+ }
+ }
set_level(0);
- int16_t diff = resting - loaded;
- uint8_t extra_blinks = 0;
+ // TODO? limit NiMH to ~half power, even if it passed the sag test?
+ // (and if so, blink 2X for NiMH, 3X for alkaline)
- if (loaded <= DUAL_VOLTAGE_LOW_LOW) {
- // weak or empty AA battery has a low limit
- ramp_level_hard_limit = WEAK_BATTERY_LOWEST_LIMIT;
- extra_blinks = 2;
- } else if (loaded >= VOLTAGE_RED) {
- // reasonably strong li-ion battery
- ramp_level_hard_limit = WEAK_BATTERY_HIGHEST_LIMIT;
- } else if (diff <= (-5 * 4)) {
- // marginal battery, dropped a lot under mild load
- ramp_level_hard_limit = WEAK_BATTERY_MEDIUM_LIMIT;
- extra_blinks = 1;
- }
+ uint8_t extra_blinks = 0;
+ if (ramp_level_hard_limit) extra_blinks ++;
for (uint8_t i=0; i<extra_blinks; i++) {
delay_4ms(300/4);
blink_once();
}
- voltage = resting;
- battcheck();
-
- voltage = loaded;
- battcheck();
+ if (ramp_level_hard_limit) {
+ delay_4ms(255);
+ // not booted far enough for this to work yet
+ //blink_num(ramp_level_hard_limit);
+ uint8_t tens, ones;
+ tens = ramp_level_hard_limit / 10;
+ ones = ramp_level_hard_limit % 10;
+ for (uint8_t i=0; i<tens; i++) {
+ delay_4ms(300/4);
+ blink_once();
+ }
+ delay_4ms(600/4);
+ for (uint8_t i=0; i<ones; i++) {
+ delay_4ms(300/4);
+ blink_once();
+ }
+ }
- //if (diff < 0)
- // blink_num(-diff);
}
-#endif
+#endif // ifdef USE_WEAK_BATTERY_PROTECTION
diff --git a/hw/hank/emisar-d3aa/hwdef.h b/hw/hank/emisar-d3aa/hwdef.h
index 1e677b6..7cd2849 100644
--- a/hw/hank/emisar-d3aa/hwdef.h
+++ b/hw/hank/emisar-d3aa/hwdef.h
@@ -116,12 +116,11 @@ enum CHANNEL_MODES {
// Alkaline AA can't handle the power this light wants,
// so try to detect it and limit the maximum power
+// (also helps protect firmware flashing adapters from overload)
#define USE_RAMP_LEVEL_HARD_LIMIT
#define USE_WEAK_BATTERY_PROTECTION
-#define WEAK_BATTERY_HIGHEST_LIMIT RAMP_SIZE
-#define WEAK_BATTERY_MEDIUM_LIMIT (RAMP_SIZE*2/3)
-#define WEAK_BATTERY_LOWEST_LIMIT (RAMP_SIZE*1/3)
-#define WEAK_BATTERY_CHECK_LEVEL (RAMP_SIZE*2/3)
+#define WEAK_BATTERY_TEST_MAX_LEVEL 75 // about 300 mA
+#define WEAK_BATTERY_SAG_THRESHOLD (5*4) // 0.5 V
// average drop across diode on this hardware
#ifndef VOLTAGE_FUDGE_FACTOR