add program to approximate cell configuration

This commit is contained in:
interfisch 2019-12-07 13:36:16 +01:00
commit d483a77903
7 changed files with 561 additions and 0 deletions

View File

@ -0,0 +1,28 @@
Label;Capacity @ 2A;+Capacity @ .5A;Capacity;Resistance [mOhm]
1 Gruen;1338;582;1920;170
2 Gruen;1228;702;1930;150
3 dunkelblau;1033;469;1502;140
4 dunkelblau;438;395;833;212
5 dunkelblau;777;411;1188;196
6 dunkelblau;1201;382;1583;140
7 dunkelblau;964;493;1457;200
8 dunkelblau;955;543;1498;208
9 dunkelblau;806;402;1208;174
10 dunkelblau;1010;426;1436;166
11 hellblau;1308;254;1562;118
12 hellblau;1440;172;1612;118
13 hellblau;1393;178;1571;114
14 hellblau;1131;590;1721;286
15 hellblau;1415;225;1640;110
16 hellblau;1454;261;1715;110
17 hellblau;1454;211;1665;108
18 hellblau;1565;184;1749;100
19 hellblau;1591;221;1812;110
20 hellblau;1538;180;1718;118
21 hellblau;1525;183;1708;108
22 hellblau;1435;213;1648;126
23 hellblau;1450;169;1619;122
24 hellblau;1503;196;1699;112
25 hellblau;1510;188;1698;130
26 hellblau;1462;230;1692;130
27 hellblau;1484;182;1666;112
1 Label Capacity @ 2A +Capacity @ .5A Capacity Resistance [mOhm]
2 1 Gruen 1338 582 1920 170
3 2 Gruen 1228 702 1930 150
4 3 dunkelblau 1033 469 1502 140
5 4 dunkelblau 438 395 833 212
6 5 dunkelblau 777 411 1188 196
7 6 dunkelblau 1201 382 1583 140
8 7 dunkelblau 964 493 1457 200
9 8 dunkelblau 955 543 1498 208
10 9 dunkelblau 806 402 1208 174
11 10 dunkelblau 1010 426 1436 166
12 11 hellblau 1308 254 1562 118
13 12 hellblau 1440 172 1612 118
14 13 hellblau 1393 178 1571 114
15 14 hellblau 1131 590 1721 286
16 15 hellblau 1415 225 1640 110
17 16 hellblau 1454 261 1715 110
18 17 hellblau 1454 211 1665 108
19 18 hellblau 1565 184 1749 100
20 19 hellblau 1591 221 1812 110
21 20 hellblau 1538 180 1718 118
22 21 hellblau 1525 183 1708 108
23 22 hellblau 1435 213 1648 126
24 23 hellblau 1450 169 1619 122
25 24 hellblau 1503 196 1699 112
26 25 hellblau 1510 188 1698 130
27 26 hellblau 1462 230 1692 130
28 27 hellblau 1484 182 1666 112

View File

@ -0,0 +1,25 @@
Label;Capacity @ 2A;+Capacity @ .5A;Capacity;Resistance [mOhm]
1 Gruen;1338;582;1920;170
2 Gruen;1228;702;1930;150
3 dunkelblau;1033;469;1502;140
5 dunkelblau;777;411;1188;196
6 dunkelblau;1201;382;1583;140
7 dunkelblau;964;493;1457;200
9 dunkelblau;806;402;1208;174
10 dunkelblau;1010;426;1436;166
11 hellblau;1308;254;1562;118
12 hellblau;1440;172;1612;118
13 hellblau;1393;178;1571;114
15 hellblau;1415;225;1640;110
16 hellblau;1454;261;1715;110
17 hellblau;1454;211;1665;108
18 hellblau;1565;184;1749;100
19 hellblau;1591;221;1812;110
20 hellblau;1538;180;1718;118
21 hellblau;1525;183;1708;108
22 hellblau;1435;213;1648;126
23 hellblau;1450;169;1619;122
24 hellblau;1503;196;1699;112
25 hellblau;1510;188;1698;130
26 hellblau;1462;230;1692;130
27 hellblau;1484;182;1666;112
1 Label Capacity @ 2A +Capacity @ .5A Capacity Resistance [mOhm]
2 1 Gruen 1338 582 1920 170
3 2 Gruen 1228 702 1930 150
4 3 dunkelblau 1033 469 1502 140
5 5 dunkelblau 777 411 1188 196
6 6 dunkelblau 1201 382 1583 140
7 7 dunkelblau 964 493 1457 200
8 9 dunkelblau 806 402 1208 174
9 10 dunkelblau 1010 426 1436 166
10 11 hellblau 1308 254 1562 118
11 12 hellblau 1440 172 1612 118
12 13 hellblau 1393 178 1571 114
13 15 hellblau 1415 225 1640 110
14 16 hellblau 1454 261 1715 110
15 17 hellblau 1454 211 1665 108
16 18 hellblau 1565 184 1749 100
17 19 hellblau 1591 221 1812 110
18 20 hellblau 1538 180 1718 118
19 21 hellblau 1525 183 1708 108
20 22 hellblau 1435 213 1648 126
21 23 hellblau 1450 169 1619 122
22 24 hellblau 1503 196 1699 112
23 25 hellblau 1510 188 1698 130
24 26 hellblau 1462 230 1692 130
25 27 hellblau 1484 182 1666 112

View File

@ -0,0 +1,109 @@
#!/usr/bin/env python3
import numpy as np
import csv
import itertools
import math
column_label=0
column_capacity=3
column_resistance=4
config_parallel=2
config_cells=12
#config_parallel*config_cells*config_packs needed
batteriesneeded=config_parallel*config_cells
batteries=[]
batterylabels=[]
with open('12S_LiIon_Akkupack_selected.csv', 'r') as csvfile:
csvreader = csv.reader(csvfile, delimiter=';')
firstrow=True
for row in csvreader:
label=row[column_label]
capacity=row[column_capacity]
resistance=row[column_resistance]
if not firstrow:
capacity=float(capacity)
resistance=float(resistance)
batteries.append([label,capacity,resistance])
batterylabels.append(label)
firstrow=False
print(str(len(batteries))+" Batteries found")
if len(batteries)==batteriesneeded:
print("You have just enough batteries")
elif len(batteries)>batteriesneeded:
print("You have "+str(len(batteries)-batteriesneeded)+" batteries spare")
elif len(batteries)<batteriesneeded:
print("You need "+str(batteriesneeded-len(batteries))+" more batteries!")
exit()
#batteries=[["a",1],["b",2],["c",3],["d",4],["e",5],["f",6]]
bestcombination=[]
bestdist=100000000
combinations=[]
count=0
for comb_parallel1 in itertools.combinations(batteries,config_parallel):
rest1=[x for x in batteries if x not in comb_parallel1]
count+=1
print(count)
for comb_parallel2 in itertools.combinations(rest1,config_parallel):
rest2=[x for x in rest1 if x not in comb_parallel2]
for comb_parallel3 in itertools.combinations(rest2,config_parallel):
rest3=[x for x in rest2 if x not in comb_parallel3]
for comb_parallel4 in itertools.combinations(rest3,config_parallel):
rest4=[x for x in rest3 if x not in comb_parallel4]
for comb_parallel5 in itertools.combinations(rest4,config_parallel):
rest5=[x for x in rest4 if x not in comb_parallel5]
for comb_parallel6 in itertools.combinations(rest5,config_parallel):
rest6=[x for x in rest5 if x not in comb_parallel6]
for comb_parallel7 in itertools.combinations(rest6,config_parallel):
rest7=[x for x in rest6 if x not in comb_parallel7]
for comb_parallel8 in itertools.combinations(rest7,config_parallel):
rest8=[x for x in rest7 if x not in comb_parallel8]
for comb_parallel9 in itertools.combinations(rest8,config_parallel):
rest9=[x for x in rest8 if x not in comb_parallel9]
for comb_parallel10 in itertools.combinations(rest9,config_parallel):
rest10=[x for x in rest9 if x not in comb_parallel10]
for comb_parallel11 in itertools.combinations(rest10,config_parallel):
rest11=[x for x in rest10 if x not in comb_parallel11]
for comb_parallel12 in itertools.combinations(rest11,config_parallel):
combinations.append([comb_parallel1,comb_parallel2,comb_parallel3,comb_parallel4,comb_parallel5,comb_parallel6,comb_parallel7,comb_parallel8,comb_parallel9,comb_parallel10,comb_parallel11,comb_parallel12])
#evaluate current combination of comb_pack1 and comb_pack2
print(str(len(combinations))+" Combinations")
for i in combinations: #every combinations
seriescapacities=[]
for s in i: #all series
parallelcapacity=0
for p in s: #all parallels
parallelcapacity+=p[1]
seriescapacities.append(parallelcapacity)
meancapacity=np.mean(seriescapacities)
dist=0
for c in seriescapacities:
dist+=math.pow(abs(c-meancapacity),2)
if dist<bestdist:
print(str(dist)+" "+str(seriescapacities))
bestdist=dist
bestcombination=i
print("best combination with "+str(bestdist)+" distance:")
#print(bestcombination)
for i in bestcombination:
print(i)

View File

@ -0,0 +1,104 @@
#!/usr/bin/env python3
import numpy as np
import csv
import itertools
import math
#https://stackoverflow.com/questions/5360220/how-to-split-a-list-into-pairs-in-all-possible-ways
def all_pairs(lst):
if len(lst) < 2:
yield lst
return
a = lst[0]
for i in range(1,len(lst)):
pair = (a,lst[i])
for rest in all_pairs(lst[1:i]+lst[i+1:]):
yield [pair] + rest
column_label=0
column_capacity=3
column_resistance=4
config_parallel=2
config_cells=12
#config_parallel*config_cells*config_packs needed
batteriesneeded=config_parallel*config_cells
batteries=[]
batterylabels=[]
with open('12S_LiIon_Akkupack_selected.csv', 'r') as csvfile:
csvreader = csv.reader(csvfile, delimiter=';')
firstrow=True
for row in csvreader:
label=row[column_label]
capacity=row[column_capacity]
resistance=row[column_resistance]
if not firstrow:
capacity=float(capacity)
resistance=float(resistance)
batteries.append([label,capacity,resistance])
batterylabels.append(label)
firstrow=False
print(str(len(batteries))+" Batteries found")
if len(batteries)==batteriesneeded:
print("You have just enough batteries")
elif len(batteries)>batteriesneeded:
print("You have "+str(len(batteries)-batteriesneeded)+" batteries spare")
elif len(batteries)<batteriesneeded:
print("You need "+str(batteriesneeded-len(batteries))+" more batteries!")
exit()
#batteries=[["a",1],["b",2],["c",3],["d",4],["e",5],["f",6]]
bestcombination=[]
bestdist=100000000
combinations=all_pairs(batteries)
num_combinations=0
#print("Counting combinations")
#for i in combinations: #just count the combinations
# num_combinations+=1
print(str(num_combinations)+" combinations possible")
#evaluate combinations
count=0
for i in combinations: #every combinations
count+=1
if count%1000000==0:
print(str(count)+"/"+str(num_combinations))
seriescapacities=[]
for s in i: #all series
parallelcapacity=0
for p in s: #all parallels
parallelcapacity+=p[1]
seriescapacities.append(parallelcapacity)
meancapacity=np.mean(seriescapacities)
dist=0
for c in seriescapacities:
dist+=math.pow(abs(c-meancapacity),2)
if dist<bestdist:
print(str(count)+"/"+str(num_combinations)+" New Best with distance "+str(dist))
bestdist=dist
bestcombination=i
print("## Combination ##")
for i in bestcombination:
print(i)
print("## ----------- ##")
print("")
print("best combination with "+str(bestdist)+" distance:")
#print(bestcombination)
for i in bestcombination:
print(i)

View File

@ -0,0 +1,157 @@
#!/usr/bin/env python3
import numpy as np
import csv
import itertools
import math
distancemeasure="max" #mse, max
column_label=0
column_capacity=3
column_resistance=4
config_parallel=2
config_cells=12
#config_parallel*config_cells*config_packs needed
batteriesneeded=config_parallel*config_cells
batteries=[]
batterylabels=[]
with open('12S_LiIon_Akkupack_selected.csv', 'r') as csvfile:
csvreader = csv.reader(csvfile, delimiter=';')
firstrow=True
for row in csvreader:
label=row[column_label]
capacity=row[column_capacity]
resistance=row[column_resistance]
if not firstrow:
capacity=float(capacity)
resistance=float(resistance)
batteries.append([label,capacity,resistance])
#batterylabels.append(label)
firstrow=False
print(str(len(batteries))+" Batteries found")
if len(batteries)==batteriesneeded:
print("You have enough batteries for "+str(config_cells)+"S"+str(config_parallel)+"P")
elif len(batteries)>batteriesneeded:
print("You have "+str(len(batteries)-batteriesneeded)+" batteries in spare")
elif len(batteries)<batteriesneeded:
print("You need "+str(batteriesneeded-len(batteries))+" more batteries!")
exit()
#calculate mean capacity of all cells
meancapacity=0
for i in batteries:
meancapacity+=i[1] #add capacities
meancapacity/=len(batteries)
print("Mean Capacity= "+str(meancapacity))
comb_parallel_all=[]
for comb_parallel in itertools.combinations(batteries,config_parallel):
comb_parallel_all.append(comb_parallel)
comb_parallel_all_meancapacities=[]
for current_parallel in comb_parallel_all:
#print(current_parallel)
meancapacity_parallel=0
for current_cell_from_parallel in current_parallel:
meancapacity_parallel+=current_cell_from_parallel[1] #add capacities
meancapacity_parallel/=len(current_parallel)
#print("Mean Capacity Parallel set="+str(meancapacity_parallel))
comb_parallel_all_meancapacities.append( meancapacity_parallel )
deviationFromMean = [abs(x - meancapacity) for x in comb_parallel_all_meancapacities]
assert len(comb_parallel_all)==len(deviationFromMean), "Menacapacity array lenght not matching"
sortedIndices=np.argsort(deviationFromMean)
bestSelection=[]
bestSelectionDistance=10000000000
def getDistanceFromSelection(selection):
if distancemeasure=="mse":
return getDistanceFromSelectionMSE(selection)
elif distancemeasure=="max":
return getDistanceFromSelectionMAX(selection)
def getDistanceFromSelectionMSE(selection): #Mean Squared Error
global deviationFromMean
distance=0
for i in selection:
distance+= math.pow(deviationFromMean[i],2)
distance/=len(selection)
return distance
def getDistanceFromSelectionMAX(selection): #Mean Squared Error
global deviationFromMean
_deviations=[deviationFromMean[x] for x in selection]
distance=max(_deviations)
return distance
def greedy(parallelCombinations,remainingSortedIndices,currentSelection):
global config_cells
global bestSelection
global bestSelectionDistance
global deviationFromMean
#print("greedy("+str(len(parallelCombinations))+","+str(len(remainingSortedIndices))+","+str(currentSelection)+")")
if len(remainingSortedIndices)<1 or len(currentSelection)>=config_cells : #nothing left
currentSelectionDistance=getDistanceFromSelection(currentSelection)
if currentSelectionDistance < bestSelectionDistance: #new best found
bestSelectionDistance=currentSelectionDistance
bestSelection=currentSelection
print("")
print("New best found "+str(currentSelection))
_print_deviationFromMean=[round(deviationFromMean[a],1) for a in currentSelection]
print("Dev. from mean "+str(_print_deviationFromMean))
print("Distance="+str(currentSelectionDistance))
for i in bestSelection:
print(str(comb_parallel_all[i])+" mc="+str(comb_parallel_all_meancapacities[i]))
return #backtrack
if len(currentSelection)>0 and getDistanceFromSelection(currentSelection)>bestSelectionDistance: #distance is already too high
return #backtrack early
for i in remainingSortedIndices: #try all in sorted order
newremainingSortedIndices=[x for x in remainingSortedIndices] #copy list, should be the same for every i
_selectedIndex=i #greedy take element i
#remove elements with one of the used batteries
for used in parallelCombinations[_selectedIndex]:
#print(used)
for rsi in newremainingSortedIndices: #check all remaining indices
containesBattery=False
for pcb in parallelCombinations[rsi]:
if pcb==used:
containesBattery=True
if containesBattery:
newremainingSortedIndices=[x for x in newremainingSortedIndices if x is not rsi] #remove current index rsi from remainingSortedIndices
#repeat until empty
greedy(parallelCombinations,newremainingSortedIndices,currentSelection+[_selectedIndex])
greedy(comb_parallel_all,sortedIndices, [])
print(bestSelection)
print("###")
for i in bestSelection:
print(str(comb_parallel_all[i])+" mc="+str(comb_parallel_all_meancapacities[i]))

View File

@ -0,0 +1,67 @@
#!/usr/bin/env python3
import numpy as np
import csv
import itertools
import math
import scipy.special
#o(n) = (n-1) * o(n-2) <- pairs
def number_pairs(size):
if size<2:
return 1
n=size-1
return n*number_pairs(size-2)
#https://stackoverflow.com/questions/5360220/how-to-split-a-list-into-pairs-in-all-possible-ways
def all_pairs(lst):
if len(lst) < 2:
yield lst
return
a = lst[0]
for i in range(1,len(lst)):
pair = (a,lst[i])
for rest in all_pairs(lst[1:i]+lst[i+1:]):
yield [pair] + rest
def all_triples(lst):
if len(lst) < 3:
yield lst
return
a = lst[0]
for i in range(1,len(lst)):
for j in range(i+1,len(lst)):
pair = (a,lst[i],lst[j])
for rest in all_triples(lst[1:i]+lst[i+1:j]+lst[j+1:]):
yield [pair] + rest
def all_quadruples(lst):
if len(lst) < 4:
yield lst
return
a = lst[0]
for i in range(1,len(lst)):
for j in range(i+1,len(lst)):
for k in range(j+1,len(lst)):
pair = (a,lst[i],lst[j],lst[k])
for rest in all_quadruples(lst[1:i]+lst[i+1:j]+lst[j+1:k]+lst[k+1:]):
yield [pair] + rest
#a=[1,2,3,4]
a=[1,2,3,4,5,6]
print(number_pairs(24))
count=0
for i in all_pairs(a):
count+=1
#print(i)
print(count)

View File

@ -0,0 +1,71 @@
import controlP5.*;
import processing.serial.*;
ControlP5 cp5;
Serial myPort; // Create object from Serial class
int val; // Data received from the serial port
float links;
float rechts;
Slider slLinks;
Slider slRechts;
void setup() {
size(450, 300);
frameRate(100);
background(0);
cp5 = new ControlP5(this);
slLinks = cp5.addSlider("links")
.setRange((float)-1, (float)1)
.setValue(0)
.setPosition(10,10)
.setSize(400,20)
;
slRechts = cp5.addSlider("rechts")
.setRange((float)-1,(float)1)
.setValue(0)
.setPosition(10,40)
.setSize(400,20);
cp5.addButton("stop")
.setPosition(10, 80)
.setSize(150, 150);
myPort = new Serial(this, "/dev/ttyUSB0", 115200);
}
void stop() {
slLinks.setValue(0);
slRechts.setValue(0);
}
void draw() {
int bits = Float.floatToIntBits(rechts);
byte[] bytes = new byte[8];
bytes[0] = (byte)(bits & 0xff);
bytes[1] = (byte)((bits >> 8) & 0xff);
bytes[2] = (byte)((bits >> 16) & 0xff);
bytes[3] = (byte)((bits >> 24) & 0xff);
bits = Float.floatToIntBits(links);
bytes[4] = (byte)(bits & 0xff);
bytes[5] = (byte)((bits >> 8) & 0xff);
bytes[6] = (byte)((bits >> 16) & 0xff);
bytes[7] = (byte)((bits >> 24) & 0xff);
myPort.write(bytes); // send an H to indicate mouse is over square
String inBuffer = myPort.readString();
if (inBuffer != null) {
println(inBuffer);
}
}