소스 검색

Use a discharge-curve lookup table for battery percentage

The previous linear map from 3.3-4.2V read the wrong percentage near
both ends of a real Li-ion/LiPo discharge curve, and didn't line up
with VI_LVL (the forced-shutdown voltage), so 0% didn't mean "about to
shut down."
k4be 1 주 전
부모
커밋
17345a7435
1개의 변경된 파일과 29개의 추가작업 그리고 5개의 파일을 삭제
  1. 29 5
      soft/syslog.c

+ 29 - 5
soft/syslog.c

@@ -186,12 +186,36 @@ void log_jump(unsigned char is_alt, float meters) {
 	xprintf(PSTR("%.1fm\r\n"), (double)meters);
 }
 
+/* Voltage->percent breakpoints for a rough Li-ion/LiPo discharge curve,
+ * anchored so VI_LVL (the level that forces an immediate shutdown, see
+ * main.h) reads 0% - not just happens to clamp there. Precision isn't the
+ * goal (a straight line between points is a rough approximation), only
+ * getting the empty end right, since that's exactly when this number matters
+ * most. Voltages are millivolts to keep the table integer. */
+__flash const unsigned int batt_lut_mv[] = { 3100, 3400, 3550, 3700, 3850, 4000, 4100, 4200 };
+__flash const unsigned char batt_lut_pct[] = {   0,   10,   25,   45,   65,   80,   90,  100 };
+#define BATT_LUT_LEN	(sizeof(batt_lut_mv)/sizeof(batt_lut_mv[0]))
+
+static unsigned char battery_percent(float bat_volt) {
+	unsigned int mv = (unsigned int)(bat_volt*1000.0 + 0.5);
+	unsigned char i;
+
+	if (mv <= batt_lut_mv[0])
+		return batt_lut_pct[0];
+	if (mv >= batt_lut_mv[BATT_LUT_LEN-1])
+		return batt_lut_pct[BATT_LUT_LEN-1];
+	for (i = 1; i < BATT_LUT_LEN; i++) {
+		if (mv <= batt_lut_mv[i]) {
+			unsigned int span_mv = batt_lut_mv[i] - batt_lut_mv[i-1];
+			unsigned char span_pct = batt_lut_pct[i] - batt_lut_pct[i-1];
+			return batt_lut_pct[i-1] + (unsigned char)((unsigned long int)(mv - batt_lut_mv[i-1]) * span_pct / span_mv);
+		}
+	}
+	return batt_lut_pct[BATT_LUT_LEN-1]; /* unreachable */
+}
+
 void log_status_line(void) {
-	signed int batpct = (signed int)((System.bat_volt - 3.3) / (4.2 - 3.3) * 100.0 + 0.5);
-	if (batpct < 0)
-		batpct = 0;
-	if (batpct > 100)
-		batpct = 100;
+	unsigned char batpct = battery_percent(System.bat_volt);
 
 	log_reject_flush();
 	log_prefix();