import serial import binascii import math import mariadb import copy # aktuell ist es so programmiert, dass es annimmt, dass in kg gemessen wird (andere Einheiten liefern also flasche Ergebnisse) # das was man noch dazuprogrammieren kann, ist wenn mehrere Teile auf der Waage liegen, ob dann die Typen noch immer erkannt werden db_config = { 'user': 'dbUser', 'password': 'dbPassword', 'host': 'localhost', 'database': 'projectGeislinger', 'port': 3306 # Standard port for MariaDB } # Establishing the connection conn = mariadb.connect(**db_config) # Create a cursor to execute queries cursor = conn.cursor() # Konfiguration der seriellen Schnittstelle ser = serial.Serial('/dev/ttyUSB0', 9600) waageEingeschwungen = False def wahrscheinlichkeitsDichte(x,mue, var): # in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet standardabweichung = var**0.5 result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2) return result def wahrscheinlichkeitsDichteMultipVar(waageMessung, numberObjectList, results): # in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable waageMessung für eine bestimmte Normalverteilung berechnet # Mathematische Sätze, auf welchen die Berechnung basiert: # seien X1,..., Xn unabhängige Zufallsvariablen mit Dichten f1,..., fn, dann hat X = (X1,...,Xn) die gemeinsame Dichte f(x1,...,xn) = f1(x1) * ... + fn(xn) # seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2 result = 0 # Berechnung vom Gesamtmittelwert mueGes = 0 for i in range(0, len(numberObjectList)): mueGes = mueGes + numberObjectList[i] * results[i][2] # Berechnung von der Gesamtvarianz (var = sigma^2) varGes = 0 for i in range(0, len(numberObjectList)): varGes = varGes + numberObjectList[i] * results[i][3] # Berechnung der Wahrscheinlichkeitsdichte standardabweichungGes = varGes**0.5 result = 1/(standardabweichungGes * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((waageMessung-mueGes)/standardabweichungGes)**2) return result # die Funktion kann man vermutlich rauslöschen def numberSmallerObjects(numberBiggerObjects, messungWaage, mue1,mue2, sigma2): for i in range(1,10000): #damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2 # eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen) if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0: if i > (messungWaage-numberBiggerObjects*mue2)/mue1: return i else: return -1 def sumMaxWeightObjects(objectType, numberObjectList, results): sum = 0 # die Anzahl an Bauteilen, welche dem Objekttypen zugeordnet sind, sollen nicht mit dazugerechnet werden for i in range(objectType+1, len(numberObjectList)): # eigentlich müsste man nur mit 3 multiplizieren, um 99,7% der Bauteile im Bereich zu haben - das gilt aber nur für eine gültige Normalverteilung #sum = sum + numberObjectList[i] * (results[i][2] + 3 * math.sqrt(results[i][3])) sum = sum + numberObjectList[i] * (results[i][2]) return sum def numberPossibleObjects(objectType, numberObjectList, results, messungWaage): # der objectType definiert, welcher der Objekte das Anschauungsobjekt ist # wenn nur ein Objekt darauf gelegt wird, welches nicht vom Typen des Anschauungsobjektes ist, dann wird 1 zurück gegeben #print(results[objectType][2]-10*math.sqrt(results[objectType][3])) #print((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/results[objectType][2]) # wenn kein Gewicht auf der Waage liegt, dann soll -1 zurück gegeben werden. if messungWaage <= 0: return -1 #print(results[objectType][2]) #print(((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]+3*math.sqrt(results[objectType][3])))) #print(((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]-3*math.sqrt(results[objectType][3])))) #zwischenSumme = ((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]+3*math.sqrt(results[objectType][3]))) zwischenSumme = ((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2])) for i in range(1,10000): if zwischenSumme <= 0: #in diesem Fall wird das gesamte Gewicht der Messung durch Objekte eines anderen Typen "aufgebraucht" return 0 if i > zwischenSumme: return i # i entspricht beim returnen der Anzahl der möglichen Objekte def anzBauteileCountFunction(numberObjectList): counter = 0 for i in range(0,len(numberObjectList)): if numberObjectList[i] > 0: counter = counter + 1 return counter """ for i in range(1,10000): #damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2 # eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen) if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0: if i > (messungWaage-numberBiggerObjects*mue2)/mue1: return i else: return -1 """ def main(): print("connection is open: ", ser.is_open) print("port to which it is connected: ", ser.portstr) #an die Waage den Befehl senden, dass sie ausgelesen werden soll ser.write(b'getWeight\n') #ser.write(b'tare\n') serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage # wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft lenString = len(serialString)-1 if serialString[lenString] == "g" and serialString[lenString-1] == "k": print("ist eingeschwungen") waageEingeschwungen = True else: print("die Waage ist noch nicht eingeschwungen") waageEingeschwungen = False #aus dem String werden alle Zeichen, welche nicht zur Darstellung der Zahl benötigt werden entfernt intString = "" for i in serialString: if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9": intString = intString + i print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg") # wenn die Waage nicht eingeschwungen ist, dann soll auch nichts weiter gemacht werden if( waageEingeschwungen == True and float(intString)>0): # Define the SQL query sql_query = "SELECT * FROM projectGeislinger.Einzelteile" # Execute the query cursor.execute(sql_query) # Fetch results results = cursor.fetchall() # Display data print("Ausgabe der Daten der Datenbank:") for row in results: print(row) anzBauteiltypen = len(results) anzBauteile = anzBauteiltypen * [0] # erstellt eine Liste, in welcher die Anzahl der Bauteiltypen gespeichert ist, welche für die weiteren Schleifen verwendet wird wahrscheinleichkeitsMatrix = [] # Berechnen der Anzahl an Objekten for i in range(0, anzBauteiltypen): #bauteilTypCounter = i+1 #zum hochzählen der Anzahlen der Bauteiltypen nach der k-Schleife while(True): if i<(anzBauteiltypen-1): # wenn i die letzte Spalte der Bauteiltypenmatrix ist, dann soll der Teil übersprungen werden for k in range(0, 10000): anzBauteile[i+1] = k nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString)) if nrObjects == -1 or nrObjects == 0: break anzBauteile[i] = nrObjects wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]]) # da die Berechnete Anzahl an möglichen Messobjekten um 0 bis +1 um den "wahren" Wert schwankt, wird in der Folge auch die Wahrscheinlichkeit mit einer um 1 verringerten Bauteilanzahl berechnet (sollte diese größer als 1 sein) if(anzBauteile[i] >= 1 and anzBauteileCountFunction(anzBauteile)>1): anzBauteile = anzBauteile[:] anzBauteile[i] = anzBauteile[i]-1 wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]]) anzBauteile[i+1] = 0 elif i == (anzBauteiltypen-1): nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString)) if nrObjects == -1 or nrObjects == 0: break anzBauteile[i] = nrObjects wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]]) if(anzBauteile[i] >= 1 and anzBauteileCountFunction(anzBauteile)>1): anzBauteile = anzBauteile[:] anzBauteile[i] = anzBauteile[i]-1 wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]]) if i >= (anzBauteiltypen-2): #wenn der Fall eintritt, dann wurden alle Fälle überprüft -> dadurch kann die i-Schleife in die letzte Runde gehen, kann das Programm sich ganz beenden anzBauteile[i] = 0 break for m in range(i+2,anzBauteiltypen): anzBauteile[m] = anzBauteile[m] + 1 nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString)) if nrObjects >= 1: break elif nrObjects < 1 and m == (anzBauteiltypen-1) : break else: anzBauteile[m] = 0 nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString)) if (nrObjects == -1 or nrObjects == 0): anzBauteile[anzBauteiltypen-1] = 0 anzBauteile[i] = 0 break # Suchen der höchsten Wahrscheinlichkeitsdichte countMaxPropDensity = 0 maxPropDensity = 0 #print(wahrscheinleichkeitsMatrix[0][0]) for i in range(0, len(wahrscheinleichkeitsMatrix)): if(wahrscheinleichkeitsMatrix[i][0] > maxPropDensity): maxPropDensity = wahrscheinleichkeitsMatrix[i][0] countMaxPropDensity = i if wahrscheinleichkeitsMatrix[i][0] >0: print(wahrscheinleichkeitsMatrix[i]) print(wahrscheinleichkeitsMatrix[countMaxPropDensity][0]) # die Bauteilkombination mit der höchsten Wahrscheinlichkeitsdichte ausgeben for i in range(0, len(wahrscheinleichkeitsMatrix[0][1])): print("Bauteiltyp: ", results[i][1]," Anzahl: ", wahrscheinleichkeitsMatrix[countMaxPropDensity][1][i]) #nrObjects = numberPossibleObjects(0, anzBauteile, results, float(intString)) #print("number objects: ", nrObjects-1) """ for i in range(3,0,-1): numberOfSmallObjects = numberSmallerObjects(1, float(intString),results[4][2], results[3][2], math.sqrt(results[3][3])) print("number of smaller objects: ", numberOfSmallObjects-1) """ """ # in der Folge wird nun berechnet, welcher Normalverteilung die Messung am ehesten entspricht dBId = 0 maxPropDensity = 0 for row in results: propDens = wahrscheinlichkeitsDichte(float(intString) ,row[2], row[3]) if propDens > maxPropDensity: maxPropDensity = propDens dBId = row[0] #Ausgabe des Bauteiltypen, welchem die Messung am ehesten entspricht for row in results: if row[0] == dBId: print(row[1]) #propDens = wahrscheinlichkeitsDichte(0.042 ,results[0][2], results[0][3]) #print(propDens) """ ser.close() print("connection is open: ", ser.is_open) if __name__ == "__main__": main()