Reply
Thread Tools
NobodyInPerson's Avatar
Posts: 52 | Thanked: 63 times | Joined on Sep 2014 @ Germany
#1
Hey everyone!

I wrote myself a script in R that saves several battery parameters of my N9 every couple of minutes, then puts this into a .csv file and creates a neat little .png graph that Billboard displays on the standbyscreen.

The change of the battery charge over time interested me because I wanted to understand these stupid 4%-drops that happen to occur everytime the N9 gets stressed with a not fully charged battery.

Things evolved and I started to log battery temperature, voltage and charging state as well to find a correlation or explanation for these drops. I didn't log the current, because I think this is highly variable and with a temporal resolution of around 5 minutes, it doesn't bring me much...

What I found out so far, is that the 4%-drops are not caused by a sudden voltage drop which I thought it was... At the moment, I don't have the time to dig further into this topic.

Anyway: I decided to share five months of logged battery data with you. Those of you who are familiar with some statistics can surely make use of it. Maybe you'll find something interesting!

See the attached .tar.bz2-file. It contains a TAB-separated-.csv-file with header which contains the following data:
  • TIME: seconds from the beginning of the 5-months-period
  • BATTERY: The system's battery charge percentage obtained with qdbus
  • CHARGING: logical value. Is the battery charging (TRUE) or not (FALSE), obtained from bmestat
  • TEMP: battery temperature in °C, obtained from bmestat. Curiously, the decimal values were constantly .85, so I just left them out.
  • VOLTAGE: battery voltage in volts obtained from bmestat

The timestep is around 5 minutes, varies and is definitely not equidistant.

-------------------------------------------------------------------------

Here are the sources:

Billboard-battery.R - the script that reads the data, saves it and produces the .png image to be displayed via Billboard on the standbyscreen.
Requirements:
  • r-base from openrepos
  • put this into folder /home/user/.billboardscripts/
Code:
#!/usr/bin/Rscript
# Billboard Battery diagram

#### Settings ####
main.hour.interval = 3
main.anz.intervals = 16
battery.file.name = "/home/user/.billboardscripts/batterydata.csv"
#battery.file.name = "batterydata.csv"
plot.file.name = "/home/user/.billboardscripts/battery-diagram.bmp"
#plot.file.name = "battery-diagram.bmp"
plot.width = 400
plot.height = 150
plot.background = "black"
plot.foreground = "white"
plot.battery.linecolor  = "green"
plot.charge.color = "yellow"
plot.tempcolor = "red"
plot.voltagecolor = "cyan"
plot.day.mark.color = "red"

# Get time
now = Sys.time()
this.hour = strftime(now, format="%H")
this.date = strftime(now, format="%F")

#### Get next main hour ####
next.main.hour = as.numeric(this.hour) + 1 # Start with this hour

# Increase until next main hour is reached
while(next.main.hour %% main.hour.interval != 0) {
	next.main.hour = (next.main.hour + 1) %% 24 # Increase
	}

# Get time objects
next.main.time = strptime(x=paste(this.date,next.main.hour),format="%F %H")
if(next.main.hour==0) { next.main.time = next.main.time+86400 }


#### Generate axis sequence ####
axis.sequence = 
	seq(from=next.main.time,
			by=paste("-",main.hour.interval," hours",sep=""),
			length=main.anz.intervals)


#### Read battery data ####
# Read actual state from system
aktstate = as.numeric(system("qdbus --system org.freedesktop.Hal /org/freedesktop/Hal/devices/bme org.freedesktop.Hal.Device.GetProperty battery.charge_level.percentage",intern=TRUE))

# Read the current charging state, TRUE if currently charging, FALSE unless
aktcharge = system("bmestat|awk '/charging state/ { print $3}'",intern=TRUE) == "STARTED"

# Read the current battery temperature
akttemp = as.numeric(system("bmestat|awk '/temperature/ {print $3}'",intern=T))

# Read current voltage
aktvoltage = as.numeric(system("bmestat|awk '/battery cur. voltage/ {print $4}'",intern=T)) / 100


# Create dataframe
batterystate = data.frame(
	TIME=now,
	BATTERY=aktstate,
	CHARGING=aktcharge,
	TEMP=akttemp,
	VOLTAGE=aktvoltage
	)

# Read older entries
if(file.exists(battery.file.name)){
	# Read the data
	batterystateold = read.table(file=battery.file.name,sep="\t",header=TRUE)
	# Create columns that do not exist
	for (col in colnames(batterystate)) if(!col %in% colnames(batterystateold)) batterystateold[col] = NA
	for (col in colnames(batterystateold)) if(!col %in% colnames(batterystate)) batterystate[col] = NA
	# Concatenate data
	batterystate = rbind(batterystate,batterystateold)
	rm(batterystateold)
	}

# Sort the data
batterystate = batterystate[order(batterystate$TIME),]

# Writeout the new data
# This only writes the last period
#write.table(file=battery.file.name,x = batterystate[which(batterystate$TIME>(min(axis.sequence))-main.hour.interval*60*60),],row.names = F,quote = F,sep="\t")
write.table(file=battery.file.name,x = batterystate,row.names = F,quote = F,sep="\t") 

# Convert date
batterystate$TIME = strptime(x = batterystate$TIME, format="%F %H:%M:%S")

# Selection to plot
selection = batterystate$TIME>=min(axis.sequence)-60*60*main.hour.interval
TIME     = batterystate$TIME[selection]
BATTERY  = batterystate$BATTERY[selection]
CHARGING = batterystate$CHARGING[selection]
TEMP     = batterystate$TEMP[selection]
VOLTAGE  = batterystate$VOLTAGE[selection]

rm(selection) # Free memory
rm(batterystate) # Free memory

#### Plot ####
# Open a graphics device
bmp(file=plot.file.name,width=plot.width,height=plot.height)

# Set graphical parameters
par(bg=plot.background,col=plot.battery.linecolor,mar=c(2,2.4,0.3,0.1)+0.01)

# Plot basic
plot(x=axis.sequence,y=rep(1,length(axis.sequence)), type="n",
		 axes=F, ylim=c(0,100))

# Draw axes
axis(side=2, # Y-Axis
		 las=2, # Write text 90 degrees
		 col=plot.foreground,col.axis=plot.foreground, # Color
		 at=seq(from=0,to=100,by=25) # Labels
		 )

# Draw box
box(col=plot.foreground)

# Draw time axis
axis.POSIXct(side=1, # X-Axis
					at=axis.sequence, # Sequence
					format="%H", # Format
					col=plot.foreground, col.axis=plot.foreground, # Color
					padj=-0.5
					)

# Draw a grid
# Horizontal lines
abline(h=seq(from=0,to=100,by=25),col="darkgrey",lty=2)
# Vertical lines
abline(v=axis.sequence,col="darkgrey",lty=2)

# Mark days
abline(v=axis.sequence[which(as.numeric(strftime(axis.sequence,format="%H"))==0)],
			 col=plot.day.mark.color,
			 lty=2)

# Draw the voltage curve
Y = VOLTAGE
lines(
	x=TIME,
	Y,
	col=plot.voltagecolor,
	lwd=4,
	pch=20,
	cex=0.1,
	)


# Draw the temperature curve
Y = TEMP
lines(
	x=TIME,
	Y,
	col=plot.tempcolor,
	lwd=4,
	pch=20,
	cex=0.1,
	)


# Draw the normal curve
Y = BATTERY
lines(
	x=TIME,
	Y,
	col=plot.battery.linecolor,
	lwd=4,
	pch=20,
	cex=0.1,
	)

#	Draw the charging curve on top
Y = BATTERY
Y[CHARGING!=TRUE|is.na(CHARGING)] = NA
lines(
	x=TIME,
	Y,
	col=plot.charge.color,
	lwd=4,
	pch=20,
	cex=0.1,
	)

# Close graphics device
dev.off()

batteryloop.sh - the stupid little endless-loop-script that calls Billboard-battery.R every 5 minutes.
Requirements:
  • put this anywhere you want and after every boot, call it from there with
    Code:
    setsid ./batteryloop.sh
Code:
#!/bin/sh
while true; do
/home/user/.billboardscripts/Billboard-battery.R
sleep 300
done
I say stupid endless-loop-script because I messed around with cron which didn't work and I tried to create an autostart entry but that turned out to not work as is should, so I had to stick to this solution. Annoying, but functional :-)

So, get your hands going!

Greetings,

NobodyInPerson
Attached Files
File Type: gz NokiaN9-batterydata-5months.tar.gz (259.6 KB, 72 views)

Last edited by NobodyInPerson; 2015-09-19 at 08:34. Reason: datafile was faulty
 

The Following 11 Users Say Thank You to NobodyInPerson For This Useful Post:
peterleinchen's Avatar
Posts: 4,118 | Thanked: 8,901 times | Joined on Aug 2010 @ Ruhrgebiet, Germany
#2
Thanks.

Nice approach (nevertheless I doubt we will find some logic in those drops ).

Why not adding the sources?
__________________
SIM-Switcher, automated SIM switching with a Double (Dual) SIM adapter
--
Thank you all for voting me into the Community Council 2014-2016!

Please consider your membership / supporting Maemo e.V. and help to spread this by following/copying this link to your TMO signature:
[MC eV] Maemo Community eV membership application, http://talk.maemo.org/showthread.php?t=94257

editsignature, http://talk.maemo.org/profile.php?do=editsignature
 
NobodyInPerson's Avatar
Posts: 52 | Thanked: 63 times | Joined on Sep 2014 @ Germany
#3
I will :-) But give me some time to grab it together in a useable form.

Edit: I updated the initial post and added the sources.

Last edited by NobodyInPerson; 2015-09-18 at 15:34.
 

The Following 2 Users Say Thank You to NobodyInPerson For This Useful Post:
NobodyInPerson's Avatar
Posts: 52 | Thanked: 63 times | Joined on Sep 2014 @ Germany
#4
Okay, here is one graph. It shows the possible calibration curve that might be used to calculate the charge of battery from the battery voltage.
The black dots are only the non-charging situations. The red dots are the heavy voltage drops like the well known 4%-drops. Since the data has a temporal resolution of around 5 minutes, I had to include the charging situations as well to get these drops, because if a drop happened, I instantly connected the charger to still use the phone.

Interesting part: Curiously, these drops in charge of battery don't come together with voltage drops, as you can see in the image. So, either the voltage sensor inside the N9 is not very precise or (most likely) the voltage is not the only indicator for the charge of battery...

Greetings,

NobodyInPerson

Edit1: I don't understand why the image gets resized so ugly... I payed attention on the maximum dimensions and file size...
Edit2: Okay, use postimg.org... that's it...


Last edited by NobodyInPerson; 2017-01-14 at 08:19. Reason: uploaded sharper image
 

The Following 7 Users Say Thank You to NobodyInPerson For This Useful Post:
NobodyInPerson's Avatar
Posts: 52 | Thanked: 63 times | Joined on Sep 2014 @ Germany
#5
I ran a fourrier transformation on the battery data to extract the typical time period of one battery cycle. Without looking at the data I would say my battery lasts one day on average. Charging over night, using over the day, and so on. Funnily, the fourrier analysis gives me exactly this result

Code:
R> source('NokiaN9-battery-period.R')
Period: 24.02245 hours
Here the code I used:

NokiaN9-battery-period.R:

Code:
# How long is battery life on the Nokia N9?
# Find the period of charge of battery

# Read CSV file
BAT <- read.csv("NokiaN9-batterydata-5months.csv", sep = "\t")

# Interpolate on regular grid
APPROX <- approx(BAT$TIME, BAT$BATTERY,xout = seq(f = min(BAT$TIME), t = max(BAT$TIME), len = length(BAT$TIME)))

# Get spectrum
SPECTRUM <- spectrum(APPROX$y,plot=F)

# Find maximum period
# First find frequency of greatest amplitude
# Invert this frequency to get the period
# Multiply this period that is in units of timesteps with the timestep to get the period in seconds
PERIOD <- 1/SPECTRUM$freq[which.max(SPECTRUM$spec)] * unique(zapsmall(diff(APPROX$x)))

# Output period in hours
cat("Period:", PERIOD / 60 / 60,"hours")

Last edited by NobodyInPerson; 2017-01-14 at 08:18.
 

The Following 4 Users Say Thank You to NobodyInPerson For This Useful Post:
Posts: 578 | Thanked: 994 times | Joined on Dec 2012
#6
Maybe you should start looking for the causes of problem at source. I mean battery charge meter.
Originally Posted by NobodyInPerson View Post
Interesting part: Curiously, these drops in charge of battery don't come together with voltage drops, as you can see in the image. So, either the voltage sensor inside the N9 is not very precise or (most likely) the voltage is not the only indicator for the charge of battery...
Originally Posted by Texas Instruments
The key to the bq27520-G2 ’ s high-accuracy gas gauging prediction is Texas Instrument ’ s proprietary Impedance Track ™ algorithm.This algorithm uses cell measurements, characteristics, and properties to create state-of-charge predictions that can achieve less than 1% error across a wide variety of operating conditions and over the lifetime of the battery.
I guess you are aware of this thread so directly reading through i2c could give you some more reliable informations.

I don't have n9 so I don't know is it really bq27520 chip or something similar.
http://www.ti.com/lit/ds/symlink/bq27520-g2.pdf
http://www.ti.com/lit/an/slua450/slua450.pdf

Last edited by elros34; 2015-09-19 at 17:32.
 
NobodyInPerson's Avatar
Posts: 52 | Thanked: 63 times | Joined on Sep 2014 @ Germany
#7
Well, that sounds interesting! But I don't have the slightest idea how to read from i2c in the N9...
 
Posts: 578 | Thanked: 994 times | Joined on Dec 2012
#8
You would need i2cget from i2c-tools package but be careful to not break your phone.
http://ruedigergad.com/2012/06/03/ne...tus-vs-n9n950/
 

The Following 2 Users Say Thank You to elros34 For This Useful Post:
NobodyInPerson's Avatar
Posts: 52 | Thanked: 63 times | Joined on Sep 2014 @ Germany
#9
Cool thing! But since I am using my beloved N9 as my one and only phone, I will keep my hands off any practice that might brick it
These guys already did an amazing piece of work there!

Last edited by NobodyInPerson; 2017-01-14 at 08:18.
 
Posts: 146 | Thanked: 99 times | Joined on Jan 2012 @ Lisbon, Portugal
#10
Funnily enough, now that I replaced the original battery on my Finnish-made N9 with a pull from (I suppose) a Lumia800, I no longer have unexpected 4% drops. This battery is less than 6 months old, though...
__________________
SGH-2100,T39i,T68m,K750,T700,N95-1,N9/64
I like to stroke my N9 - My preciousssss....
Need Portuguese (European) localizations? Ask me.
 
Reply

Tags
battery n9


 
Forum Jump


All times are GMT. The time now is 21:52.