Browse Source

add program to approximate cell configuration

master
interfisch 2 years ago
commit
d483a77903
  1. 28
      akkuconfig/12S_LiIon_Akkupack.csv
  2. 25
      akkuconfig/12S_LiIon_Akkupack_selected.csv
  3. 109
      akkuconfig/akkupack_config (Kopie 1).py
  4. 104
      akkuconfig/akkupack_config.py
  5. 157
      akkuconfig/akkupack_config_greedy.py
  6. 67
      akkuconfig/combinationstest.py
  7. 71
      akkuconfig/hoverboard_serial_test (von lucas).pde

28
akkuconfig/12S_LiIon_Akkupack.csv

@ -0,0 +1,28 @@ @@ -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

25
akkuconfig/12S_LiIon_Akkupack_selected.csv

@ -0,0 +1,25 @@ @@ -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

109
akkuconfig/akkupack_config (Kopie 1).py

@ -0,0 +1,109 @@ @@ -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)

104
akkuconfig/akkupack_config.py

@ -0,0 +1,104 @@ @@ -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)

157
akkuconfig/akkupack_config_greedy.py

@ -0,0 +1,157 @@ @@ -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]))

67
akkuconfig/combinationstest.py

@ -0,0 +1,67 @@ @@ -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)

71
akkuconfig/hoverboard_serial_test (von lucas).pde

@ -0,0 +1,71 @@ @@ -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);
}
}
Loading…
Cancel
Save