1 /*
2  * Copyright (c) 2018-2019 Peter Bigot Consulting, LLC
3  * Copyright (c) 2019 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <math.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #include <zephyr/kernel.h>
13 #include "battery.h"
14 
15 /** A discharge curve specific to the power source. */
16 static const struct battery_level_point levels[] = {
17 	/* "Curve" here eyeballed from captured data for the [Adafruit
18 	 * 3.7v 2000 mAh](https://www.adafruit.com/product/2011) LIPO
19 	 * under full load that started with a charge of 3.96 V and
20 	 * dropped about linearly to 3.58 V over 15 hours.  It then
21 	 * dropped rapidly to 3.10 V over one hour, at which point it
22 	 * stopped transmitting.
23 	 *
24 	 * Based on eyeball comparisons we'll say that 15/16 of life
25 	 * goes between 3.95 and 3.55 V, and 1/16 goes between 3.55 V
26 	 * and 3.1 V.
27 	 */
28 
29 	{ 10000, 3950 },
30 	{ 625, 3550 },
31 	{ 0, 3100 },
32 };
33 
now_str(void)34 static const char *now_str(void)
35 {
36 	static char buf[16]; /* ...HH:MM:SS.MMM */
37 	uint32_t now = k_uptime_get_32();
38 	unsigned int ms = now % MSEC_PER_SEC;
39 	unsigned int s;
40 	unsigned int min;
41 	unsigned int h;
42 
43 	now /= MSEC_PER_SEC;
44 	s = now % 60U;
45 	now /= 60U;
46 	min = now % 60U;
47 	now /= 60U;
48 	h = now;
49 
50 	snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u",
51 		 h, min, s, ms);
52 	return buf;
53 }
54 
main(void)55 int main(void)
56 {
57 	int rc = battery_measure_enable(true);
58 
59 	if (rc != 0) {
60 		printk("Failed initialize battery measurement: %d\n", rc);
61 		return 0;
62 	}
63 
64 	while (true) {
65 		int batt_mV = battery_sample();
66 
67 		if (batt_mV < 0) {
68 			printk("Failed to read battery voltage: %d\n",
69 			       batt_mV);
70 			break;
71 		}
72 
73 		unsigned int batt_pptt = battery_level_pptt(batt_mV, levels);
74 
75 		printk("[%s]: %d mV; %u pptt\n", now_str(),
76 		       batt_mV, batt_pptt);
77 
78 		/* Burn battery so you can see that this works over time */
79 		k_busy_wait(5 * USEC_PER_SEC);
80 	}
81 	printk("Disable: %d\n", battery_measure_enable(false));
82 	return 0;
83 }
84