printer-monitor icon indicating copy to clipboard operation
printer-monitor copied to clipboard

Adding battery shield for full wireless use

Open FireDemon007 opened this issue 5 years ago • 8 comments

Adding a battery shield for full Wireless use is without a doubt possible. But I'm wondering if you could read the battery level through one of the analog pins every so often and display it on the display?

FireDemon007 avatar Jul 08 '18 12:07 FireDemon007

That would be nice!

NeoRame avatar Jul 19 '19 01:07 NeoRame

I'd love to see a battery indicator next to the RSSI graph. You just need to add 220k resistor (allowing to measure up to 5.4V to be on a safe side) in series with the battery to ADC pin to have 440k/100k voltage divider (D1 has 220k/100k divider by default on ADC pin, so you can measure 3v3).

I'm working on botching the sketch to make little battery display charge of battery, will probably share the code tomorrow. For some reason I can't upload code to my D1 after uploading this project (port unable to be opened) so will try tomorrow.

Oxmaster avatar Aug 06 '19 16:08 Oxmaster

So I finished writing the botch, and did some testing on battery life. Without this mod, the monitor lived for about 24 hours of idling (RPi connected, not printing) on 2000mAh battery, so it shouldn't be shorter than this with this mod.

Add this to your printermonitor.ino at line 1012 (after the function void drawRssi(OLEDDisplay *display) and add drawBattery(display); to void drawRssi(OLEDDisplay *display) function after line 1010 (before the end of the function). So whenever the RSSI graph is updated, so is the battery status. I suggest you calibrate your resistors, as it could vary quite a lot depending on the tolerance of the resistor itself.

As I said this is a quick botch, it could use options to add sleep to prolong the battery life etc. and I didn't do any real testing, as I'm in the process of designing case for 2×18650, 128×64 OLED, D1 mini and TP4056 or battery shield module.

void drawBattery(OLEDDisplay *display){
	/* Battery botch by Oxmaster
	* ------------------------------------------------
	* add this snippet to printermonitor.ino
	* right after void drawRssi(OLEDDisplay *display)
	* and drawBattery(display); at the end of
	* drawRssi function (above this one)
	* whenever the RSSI graph is updated, so is this
	*-------------------------------------------------
	* When using D1 battery shield:
	*
	* The shield has integrated 130k resistor, just
	* bridge J2 connector on the back
	* change voltageDividerRatio to 4.5
	* and batteryVoltageRange = {3.1, 4.15}
	*-------------------------------------------------
	* When using TP4056
	*
	* Add 220k resistor inline with the battery
	* Battery -> 220k resistor -> ADC0
	* change voltageDividerRatio to 5.1
	* and batteryVoltageRange = {2.5, 4.15}
	*-------------------------------------------------
	*
	* to get better accuracy, calibrate the voltageDividerRatio
	*/

	// constants -------------------------------------------------------

	// 1 bit equals x volts
	const float bitPerVolt = 0.0009765625;

	// voltage divider ratio (use to calibrate your divider)
	// use different arduino sketch to get this value
	const float voltageDividerRatio = 5.1;
	//const float voltageDividerRatio = 4.5;

	// min and max voltage that the battery will achieve
	// used to calculate percentage of charge
	
	// per TP5400 datasheet (D1 battery shield)
	//const float batteryVoltageRange[2] = {3.1, 4.15};

	// per TP4056 datasheet
	const float batteryVoltageRange[2] = {2.5, 4.15};

	// vars ------------------------------------------------------------
	// !! do not change !!

	const uint8_t dataPoints = 5;
	static uint8_t dataIndex = 0;
	static int8_t dataReadings[dataPoints] = {0, 0, 0, 0, 0};
	static int16_t dataTotal = 0;
	int8_t average = 0;

	// calculations ----------------------------------------------------
	uint16_t adcOutput = analogRead(A0);

	// calculate voltage
	float batteryVoltage = (float)adcOutput * bitPerVolt * voltageDividerRatio;

	// convert voltage to percentage (map function)
	// int16 because the value could go above 128, overflowing int8
	int16_t batteryChargePercentage = (batteryVoltage - batteryVoltageRange[0]) * 100 / (batteryVoltageRange[1] - batteryVoltageRange[0]);

	// constrain the value in case of anomaly
	batteryChargePercentage = constrain(batteryChargePercentage, 0, 100);

	// using running average, calculate the charge percentage
	dataTotal -= dataReadings[dataIndex];
	dataReadings[dataIndex] = batteryChargePercentage;
	dataTotal += dataReadings[dataIndex];
	dataIndex ++;

	if (dataIndex >= dataPoints)
		dataIndex = 0;

	average = dataTotal / dataPoints;

	// debug
	/*
	Serial.print("ADC: ");
	Serial.println(adcOutput);
	Serial.print("VOLT: ");
	Serial.println(batteryVoltage);
	Serial.print("PERCENT: ");
	Serial.println(batteryChargePercentage);  
	Serial.print("PERCENT AVG: ");
	Serial.println(average);
	*/
	
	// draw the battery outline
	display -> drawRect(104, 49, 7, 15);

	// fill the battery, 5 steps
	// 0, 25, 50, 75, 100%

	if (average <= 0){
		// 0%
		
	} else if (average > 0){
		// 25%
		display -> drawRect(106, 60, 3, 2);
		
		if (average >= 25){
			// 50%
			display -> drawRect(106, 57, 3, 2);

			if (average >= 50){
				// 75%
				display -> drawRect(106, 54, 3, 2);

				if (average >= 75){
					// 100%
					display -> drawRect(106, 51, 3, 2);

				}
			}
		}
	}
}

This is how it looks: 0percent 100percent

File that you can just replace: printermonitor.zip

Oxmaster avatar Aug 07 '19 19:08 Oxmaster

To expand the battery live, you may can take a look to my night mode ( I started a pull request) with the darker display the battery life expand around 50-100% longer in my tests

NeoRame avatar Aug 07 '19 19:08 NeoRame

When I will have time (if) I will try to understand how the web interface works and try to implement it "properly" with settings etc. Unless someone more knowledgeable is up to the task.

Oxmaster avatar Aug 07 '19 19:08 Oxmaster

Next week when I’m home I’ll take a look and try to add this function to my monitor. Maybe I need a schematic where I put the resistors...

NeoRame avatar Aug 08 '19 10:08 NeoRame

On Sunday I will try to upload the schematic and a sketch to help calibrate the divider, maybe earlier, don't know as I have a lot of work this week.

Oxmaster avatar Aug 08 '19 10:08 Oxmaster

Again, I didn't test it too much, just verified that it works for me.

https://github.com/Oxmaster/VoltageDividerCalibration

Oxmaster avatar Aug 09 '19 18:08 Oxmaster