You should probably just use a purpose built charger or use the MCU to perform a conditional charging algorithm. Battery lifetime and safety may be improved if you never let the cell get near or above its maximum recommended cell voltage and never near or below its minimum recommended cell voltage.
Applying just a few mA of charge current may work OK if you limit the maximum voltage to well under the cell's maximum charge voltage but still it is best not to float charge them and instead let them discharge until they're -5% or more from their maximum charge termination voltage and only then start another top off charge to bring them up to nearer 100% charge.
For a common cell with a 4.20V maximum charge voltage you might instead limit the maximum charge voltage to somewhere around 3.75 volts for cell longevity purposes, and limit the current to something like C/20 where C = the nominal cell mAh capacity. If the battery has any kind of internal gas gauge circuit it might not work entirely properly if your charge currents are too low but somewhere around the lesser of C/20 or 55mA should usually be a fine relatively slow charging current.
Limit your end of discharge cut off voltage point to 3.0V or whatever the cell manufacturer suggests and you should be fine on the low end.
So if your MCU can monitor the battery voltage it might just do something like enabling charging to begin between 2.8V and 3.6V open circuit cell voltage and otherwise disable charging due to too low cell voltage or sufficiently high cell voltage. During a charge charge until say 3.75V or until something like a capacity limit of the C rate of the battery has passed into the battery at your charge current level or a timeout of XX hours where XX is appropriate relative to the cell C capacity and your C/XX charging rate.
Sometimes what looks simple is not that simple. You have a quite complex measurement to do, but you want a simple result. What you want to measure is not constant, it's varying in time. Depending on your level of requirement, you could compute one or many properties of the current consumption. These properties will help you to better monitor the system. I propose you 3 different solutions, in ascending complexity.
Solution 1: Average
You want to get a one-value result -> get the average in time. As already proposed by @akellyirl, use a low-pass filter. Compute float y = alpha*input + (1-alpha)*y
for each sample, where alpha
is the smoothing factor. See Wikipedia for the details.
Solution 2: Max + Average
You are interesting in getting the average, and the max value. Monitoring the max value could be interesting for component dimensioning for example.
if (y > max)
max = y;
Solution 3: Standard deviation + Max + Average
Why?
See below charts. There are 3 signals of different shapes. A triangle, a sine, and a spike signal. They are all periodic with same period, same amplitude, same average, and same min and max. But, they have different shapes, and indeed they have a completely different story...
One of the difference is the standard deviation. That's why I suggest you to extend your measurements, and include the standard deviation. The problem is that the standard way to compute it is CPU consuming. Hopefully, there is one solution.
How?
Use the histogram method. Build an histogram of all the measurements, and extract efficiently the statistics (min, max, avg, standard deviation) of the dataset. The histogram groups values together that have the same value, or same range of value. The advantage is to avoid storing all the samples (increasing count in time), and to have a fast computation on a limited number of data.
Before starting acquiring measurements, create an array to store the histogram. It is a 1 dimension integer array, of size 32 for example:
int histo[32];
Depending on the range of the ammeter, adapt below function. For example, if the range is 256mA it means that bin 0 of the histogram will be incremented by value between 0 and 8 mA, bin 1 by value between 8 and 16 mA etc...So, you'll need an integer to represent the histogram bin number:
short int index;
Each time you get a sample, find the corresponding bin index:
index = (short int) floor(yi);
And increment this bin:
histo[index] += 1;
To compute the mean, run this loop:
float mean = 0;
int N = 0;
for (i=0; i < 32 ; i++) {
mean = i * histo[i]; // sum along the histogram
N += i; // count of samples
}
mean /= N; // divide the sum by the count of samples.
mean *= 8; // multiply by the bin width, in mA: Range of 256 mA / 32 bins = 8 mA per bin.
To compute the standard deviation, run this loop:
float std_dev = 0;
for (i=0; i < 32 ; i++) {
std_dev = (i - mean) * (i - mean) * histo[i]; // sum along the histogram
}
std_dev /= N; // divide the sum by the count of samples.
std_dev = sqrt(std_dev); // get the root mean square to finally convert the variance to standard deviation.
The strategy of the histogram method is to make the slow operations on a few number of bins, instead of all the acquired signal samples. The longer the sample size, the better. If you want more details, read this interesting page The Histogram, Pmf and Pdf.
Best Answer
If this is a 'design time' measurement to prove the system or its scheduling on the bench, then you could use a technique that I have often used in the past.
Take a large electrolytic capacitor, and I mean 10,000uF or suchlike, and use that to power the microcontroller. Record its change of voltage second by second, which multiplied by the caapcitance will give you the integrated charge that the controller has used.
Obviously every so often you will need to charge it by connecting a power supply, to keep its voltage within the acceptable range for the micro.
There are two calibrations to make, both fairly easy.
One is what the leakage current of the capacitor is, record the voltage over time with no load on it. You might want to buffer your meter with a low bias op amp like TL081. The leakage may change over time, but with a high quality capacitor, especially if reformed at a voltage well above 3v (obviously within the rated voltage of the capacitor) it should be adequately small and stable.
The second is the actual value of the capacitance, electrolytics are notorious for wide tolerances like -20/+80%. Having established the leakage current, add a further load of a resistor, and plot the rate of voltage fall. The resistor and voltage will give you a current, over time will give you a charge, and charge per change of voltage gives you the capacitance.