Legoteil Zählmaschine 2016
Bei der HSHL Lego® Zählmaschine handelt es sich um eine Maschine, die automatisch Legoteile zählen und sortieren kann, um gegebenen Falls fehlende Lego®-Steine nachbestellen zu können. Es ist ein studentisches Projekt, welches in Rahmen des System-Entwurf-Praktikums des Studiengangs Mechatronik mit Schwerpunkt System Design Engineering im 6. Semester durchgeführt wurde.
Aufgabenstellung
Die vorhandene Legoteilzählmaschine (siehe Legoteilzählmaschine_2015 ) soll Soft- und Hardwaremäßig modifiziert werden, um weitere Anforderungen zu erfüllen.
Liste der offenen Punkten vom letzten Semester
- Neues 24 V Netzteil, 24V/10A Netzteil gegen 24V/20A austauschen, um Überlast beim Lauf aller Motoren zu verhindern. Neues Netzteil ist vorhanden.
- Software zur Bildverarbeitung (BV), Die Einbindung einer geeigneten Software zur Teileerkennung steht noch aus. Kommunikation mit Systems sowie Ansteuerung ist fertig. Bildverarbeitung mit 'String' als Output.
- Bauteileliste in Excel, Die Excel Liste, welche alle Teile eines Baukasten erhält, muss mit dem Ergebnis der BV abgeglichen werden. Erkannte Teile in mindestens zwei möglichen Ausrichtungen müssen erkannt und in der Liste vermerkt werden.
- Servo für Teilesortierung, Identisches Servo wie bisher gegenüberliegend montieren, um drei Sortierfächer (Erkannt/Nicht Erkannt/Fremdteil) zu sortieren, Konstruktion, Bestellung wurde an Fr. König geleitet.
- Dieser Punkt wird in diesem Projekt nicht bearbeitet.
- Zeit bis zur Servoöffnung, Das Delay zwsichen Befehl und öffnen der Servos muss ermittelt und je nach Geschwindigkeit angepasst werden. Es ist problemlos möglich, einen weiteren 'String' - Befehl als Buchstaben für die Verzögerungszeit einzubinden, String auslesen und verarbeiten muss in Arduino Software geschehen.
- Kabelkanal montieren, Kabelkanal zur ordentlichen Verlegung der Leitungen an den Förderbändern montieren
- Kamerahalterung, Konstruktion einer Kamerahalterung für die Logitech C920 WebCam Vorschlag: Brücke über Förderband.
- Bildverarbeitungskasten, Für die Bildverarbeitung muss eine der gebauten Bildverarbeitungsbox-Prototypen ausgewählt und montiert werden. Hierfür wurden Lichttests durchgeführt. Ergebnisse sind protokolliert SVN Link zu den Lichttests, Prototypen der Lichtboxen vorhanden.
- Teilezentrierung, Die provisorisch aus Holz gefertigte Teilezentrierung soll in fixierbarer Variante aus Aluminium gefertigt werden. Ergebnisse zu den Tests der Zentrierungsmethoden sind in diesem SVN Ordner protokolliert, Prototypen der gewählten Teilezentrierung ist vor der Bildverarbeitungsbox verbaut.
- Idee Software: Flexible Bildverarbeitungssoftware, Durch definieren der Schnittstellen könnte in der GUI eine Einbindung frei wählbarer BV Software realisiert werden. Optimal geeignet um kleine Projekte dann an der Legoteilzaehlmaschine zu testen.
- Wird in diesem Projekt nicht bearbeitet.
Aufgabenteilung inkl. weiteren Aufgaben aus dem Pflichtenheft
Es wurden für jede Aufgabe ein oder mehrere Verantwortliche(n) aus der Gruppe festgelegt. Jede Person ist dann dafür zuständig, dass diese Aufgaben erfüllt werden. Bei Bedarf steht dieser Person die ganze Gruppe zur Hilfe zur Verfügung.
- Kevin Penner:
- Separierung und Zentrierung der Lego-Teile
- Pflichtenheft Dokumentation mit Software "DOORS"
- Bildverarbeitung/Legoteil-Erkennung
- Simon Hanemann:
- GUI Programmierung
- Dokumentation in HSHL-Wiki
- Video-Anleitung
- Adam Frankhauser:
- Elektr. Sicherheit
- Bildverarbeitungs-Box Fixierung/Stabilisierung
- Video-Anleitung
- Niklas Lingenauber:
- Datenbankanbindung IN/OUT und Listen
- Projektplanung
- QM-Tests (nach Rücksprache mit Prof. Schneider auf das nächste Semester verlegt)
- Bildverarbeitung/Legoteil-Erkennung
- Sergej Krause:
- Teach-IN Funktion
- Datenbankanbindung IN/OUT und Listen
- Separierung und Zentrierung der Lego-Teile
- Christo Tsibadze:
- Projektplanung
- Bildverarbeitung/Legoteil-Erkennung
- Visualisierung von Prozessen mit "Visio"
Projektplan
Meilensteine für das 6. Semester mit Deadlines:
- 06.06.2016: Hardware und Software Inbetriebnahme
- Inbetriebnahme "Erprobung von Sensoren und Aktoren"
- Automatische Sortierung von mind. 30 Teilen
- Sortierung: Erkannt und Nicht-Erkannt
- Bildverarbeitung in "Echtzeit" am PC
- Ausgabe der Inventurliste
- 24.06.2016: Algorithmen:
- Optimierung der Bildverarbeitung
- Automatische vollständige Sortierung: NXT-Basis + Erweiterung
- Planung und Beschaffung der Hardware-Änderung (Auswerfer) für die nächste Projektphase
- 14.11.2016: wird noch festgelegt, entweder Auswerfer- oder Separierung vor der BV Optimierung
- 16.01.2016: Algorithmen Optimierung, Teach-In XT/EV3 und Report
Realisierung
Main-Funktion
Die Mainfunktion ist das Hauptprogramm der Legozählmaschine. Sie ruft nach Start des Programmes alle weiteren Module und Funktionen auf. Zu Beginn des Programmes startet die Main-Funktion eine Initialisierung. Hier werden allgemeingültige Aspekte, wie globale Variablen, Verbindungen zu Datenbank oder Kamera und Einstellungen vorgenommen. Anschließend wird ein Grafisches User-Interface aufgerufen, welches dem User ermöglicht die Legozählmaschine zu steuern. Sind notwendige Schritte wie die Auswahl von Baukästen oder dem manuellen Zählen von Bauteilen, die die Maschine nicht erkennen kann abgeschlossen, startet die automaische Erkennung der Legoteile. Der Anwender muss hier den Inhalt einer Kiste in den Förderbunker geben, die Maschine befördert die Teile automatisch in den Kamera-Raum und ermittelt durch Bildverarbeitung die enntsprechenden Bauteile. Nach Beendigung des automatischen Zählprozesses werden die Ergebnisse des manuellen und des automatischen Zählens in einer Liste zusammengefasst und die gewonnen Informationen können in einer Inventurliste ausgegeben werden. Fehlende Legoteile werden in einer seperaten Fehlteilliste ausgegeben.
Die Main-Funktion hat folgenden Aufbau:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Main-Funktion %
% %
% Funktion : Die Mainfunktion ist das Hauptprogramm der %
% Legozählmaschine. Sie ruft nach Start des Programmes %
% alle weiteren Module und Funktionen auf. %
% %
% Implementation : MATLAB R2015a %
% %
% Autor : Niklas Lingenauber %
% %
% Änderungsdatum : 24.06.2016 %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;
close all;
delete(instrfindall);
%% Initialisierung %%
%Variablen definieren
DatenbankVerbindung = database.ODBCConnection('Lego','root',''); %Adresse zur SQL, wenn=0 wird statt SQL eine ExcelListe genutzt
% GUI interne Parameter
titel = 'HSHL LEGO Zählmachine 0.5.1'; % Titel
aufloesung = get (0, 'Screensize'); % Automatisches einlesen der Bildschirmaufloesung
AufloesungX = aufloesung (3); % einlesen der Bildschirmbreite
AufloesungY = aufloesung (4); % einlesen der Bildschirmhoehe
%% Webcam Einstellungen %%
cam = webcam('Logitech HD Pro Webcam C920');
pause(1) %in seconds
cam.BacklightCompensation = 0;
pause(1) %in seconds
cam.ExposureMode = 'manual';
% pause(1) %in seconds
cam.FocusMode = 'manual';
% pause(1) %in seconds
cam.WhiteBalanceMode = 'manual';
cam.Tilt = 0;
cam.Sharpness = 128;
cam.Pan = 0;
cam.Saturation = 200;
cam.Exposure = -2;
cam.Focus = 20;
cam.Brightness = 128;
cam.Contrast = 128;
cam.WhiteBalance = 5200;
cam.Gain = 0;
pause(1) %in seconds
%% Arduino/Motor Einstellungen %%
system = 1;
motor1 = 10;
motor2 = 25;
motor3 = 40;
Serial_Interface = serial('COM4','baudrate',115200); % Create serial port
fclose(Serial_Interface);
pause(1) %in seconds
% Open serial port OR set testmode (serial port to Command Window)
try
fopen(Serial_Interface); % Open serial port
pause(1) %in seconds
testmode = 0;
catch
fprintf(1,'Serial-Port nicht verfügbar - ');
testmode = 1;
end
serialstring = ['S', num2str(system), 'A', num2str(motor1, '%03d'), 'B', num2str(motor2, '%03d'), 'C', num2str(motor3, '%03d')];
%% Relative Ordner %%
SRC_Ordner = cd;
% Pfad der oberster Ordner der GUI-Daten
GUI_Ordner = 'GUI'; % Ordner der GUI definieren
GUI_ZwischenOrdner = '2016 - GUI - Zaehlprozess'; % Name des Unterordners
GUI_Ordner = [GUI_Ordner,'\',GUI_ZwischenOrdner]; % Pfad zusammensetzen
% Interner Ordner-Pfade der GUI
GUI_Hauptfensterordner = 'GUI_Mainwindows'; % Ordner indem die Hauptfenster der GUI gespeichert sind
GUI_PopUpordner = 'GUI_PopUps'; % Ordner indem die Pop-Up-Fenster der GUI gespeichert sind
GUI_Bildordner = 'GUI_Pictures'; % Ordner indem die Bilder der GUI gespeichert sind
GUI_Datenbankordner = 'GUI_Database'; % Ordner indem die Funktionen sind, die mit der Datenbank agieren
% Formatierung (vereinfacht die Folgeschritte)
GUI_Hauptfensterordner = [SRC_Ordner,'\', GUI_Ordner,'\',GUI_Hauptfensterordner]; %Pfad-Definition
GUI_PopUpordner = [SRC_Ordner,'\', GUI_Ordner,'\',GUI_PopUpordner]; %Pfad-Definition
GUI_Bildordner = [SRC_Ordner,'\', GUI_Ordner,'\',GUI_Bildordner]; %Pfad-Definition
GUI_Datenbankordner = [SRC_Ordner,'\', GUI_Ordner,'\',GUI_Datenbankordner]; %Pfad-Definition
% Pfad des automatischen Zählen
Zaehlen= [SRC_Ordner, '\', 'Bildverarbeitung\Tracking\Algorithmus und Module'];
% Pfad des automatischen Zählen
InventListe= [SRC_Ordner, '\', 'Inventurliste'];
InventurlisteName=[InventListe, '\', 'InventurListe.xls']; %Name der InventurExcelListe
%% Aufruf der GUI %%
% Speichern der Parameter in einen gemeinsamen Datenverbund
GUI_Parameter = {titel; AufloesungX; AufloesungY; GUI_Ordner;
GUI_Hauptfensterordner; GUI_PopUpordner; GUI_Bildordner;
GUI_Datenbankordner; DatenbankVerbindung};
% Start der GUI
path(GUI_Hauptfensterordner, path); % Setzen des Pades fuer die GUI
%Wähle Baukasten
[GStatus, GKastenID_IDs, GKastenID_text] = GUI_HSHL_SDE16_INIT(GUI_Parameter'); % Start der GUI
if GStatus ~= -1 %Wenn mindestens ein Kasten ausgewählt wurde
%Trage Teile ein, die Handgezählt werden
[GStatus, GManuelleListe] = GUI_HSHL_SDE16_MANZ(GUI_Parameter,GKastenID_IDs,GKastenID_text); % Start der GUI
for i=1:length(GManuelleListe)
a(i,1)=str2num(GManuelleListe{i,1});
end
a(:,2)=cell2mat(GManuelleListe(:,2));
%% Automatische Zählprozess %%
%Bänder starten
if (testmode == 1)
fprintf(1,'%s',serialstring);
else
fprintf(Serial_Interface,'%s',serialstring);
pause(0.01) %in seconds
end
%Legoteile erkennen und Queue mit den erkannten IDs zurückgeben
path(Zaehlen, path);
AutomTeile = AutomatischesZaehlen(cam, DatenbankVerbindung, Serial_Interface);
%Bänder stoppen und serielle Schnittstelle schließen
serialstring = ['S', num2str(0)];
fprintf(Serial_Interface,'%s',serialstring);
pause(1);
fclose(Serial_Interface);
delete(instrfindall);
%Zählen der IDs
path(InventListe, path);
AutomTeile = CountIDs(AutomTeile);
if GStatus ~= -1 %Wenn manuell gezählte Teile übergeben wurden
%Zusammenführen der handgezählten und automatisch gezählten Teile
LegoTeile = vertcat(AutomTeile,a);
else
LegoTeile = AutomTeile;
end
%% Korrektur %%
%Eventuell anpassen der gezählten Teile durch den Anwender
%% Erstellen einer Inventurliste in Excel %%
%Template erstellen (Erwartete Legoteile der Baukästen eintragen)
InventurListeContent = InventurlistenTamplateMultiKaesten(GKastenID_IDs, InventurlisteName, DatenbankVerbindung);
%Eintragen der gezählten Anzahlen inkl. Ergänzung anderer gezählter Teile
InventurlisteFuellen(InventurlisteName, InventurListeContent, LegoTeile, DatenbankVerbindung);
%% Öffnen der Liste %%
winopen(InventurlisteName);
end
GUI
Unter GUI (Graphical User Interface oder auch Grafische Benutzeroberfläche versteht man die Die Schnittstelle eines Programms für einen Menschlichen Nutzer. GUI dienen meist zu Eingabe und Ausgabe von Werten die durch ein Hauptprogramm berechnet werden, dabei haben GUI in der Regel nur wenig Rechenaufwand und dienen dem Benutzer Komfort. Die GUI der HSHL Legoteil-Zählmaschine lässt sich in folgende Bereiche aufteilen:
- Auswahl des Baukastens
- Manuelles Zählen der Bauteile
- Autonomes Zählen der Bauteile
- Korrektur des autonomen Zählens
In jedem Schritt gibt es die Möglichkeit auf Hilfe zuzugreifen. Man findet einen „Hilfe“-Knopf in der Taskleiste oben links.
Auswahl der Baukästen
Im ersten Schritt müssen die Baukästen ausgewählt werden, die gezählt werden sollen. Es ist derzeit jedoch nur möglich einen Kasten aus zu wählen. In Zukunft soll es die Möglichkeit geben, zwei Kästen gleichzeitig auswählen zu können (Beispielsweise ein Hauptkasten und Zusatzkasten). Die Auswahl des Baukastens ist für die folgenden Schritte von Bedeutung. Sollte mindestens ein Kasten ausgewählt werden, so kann man mit dem nächsten Schritt dem manuellen Zählen fortfahren.
Manuelles Zählen
Wenn der im ersten Schritten gewählte Kasten Legoteile besitzt, die für den Zählprozess ungeeignet sind, müsse diese Teile vom Benutzer der Zählmaschine manuell gezählt werden. In diesem Schritt wird eine Tabelle mit den wichtigsten Eigenschaften der manuellen Teile gezeigt. Zudem wird dem Benutzer ein Bild des jeweiligen Bauteils angezeigt was er gerade in der Tabelle markiert. Ein Fortfahren ist nur möglich, wenn der Benutzer für jedes Teil eine positive ganze Zahl eingibt.
Autonomes Zählen
Es taucht nur ein Hinweisfenster Auf welches den Benutzer informiert, dass der Autonome Zählprozess bereits begonnen hat. Man kann den Prozess durch das Drücken von ESC beenden.
Korrektur des Autonomen Zählens
Am Ende des Autonomen Zählprozess werden alle gezählten Teile angezeigt. Sollten bei autonomen Zählprozess Teile falsch erkannt werden, so hat der Benutzer die Möglichkeit die die Anzahl der Teile noch einmal manuell zu korrigieren. Nicht gezählte Teile können aber auch zurück in den Zählprozess geführt werden.
Bildverarbeitung/Legoteil-Erkennung
Bildverarbeitung_Main_Funktion
Die automatische Legoteilerkennung erfolgt mit der Funktion: AutomatischesZaehlen.m (Main-Funktion der Bildverarbeitung) und weiteren kleineren Funktionen realisiert. Als Übergabeparameter erhält die Main-Funktion die Schnittstellen zu der Webcam, Datenbank und serieller Schnittstelle und liefert im Gegenzug eine chronologische Liste mit Legoteil-IDs, welche beim automatischen Zählen erkannt wurden. Zu Beginn dieser Main-Funktion werden einmalig diverse Parameter und Variablen angelegt und initialisiert. Anschließend wird in der äußeren Schleife folgendes wiederholt durchgeführt (bis Betätigung der "Escape"-Taste):
- Bild bzw. Frame wird von der Kamera eingelesen
- Ränder werden weggeschnitten
- Mit Gauß-Filter gefiltert
- Bild wird in Rot-, Grün- und Blau-Anteilen separiert
- Anschließend werden nur die Pixeln aus dem Bild in verschiedenen Binär-Bildern kopiert, die der Lego-Farben entsprechen --> Vorsegmentierung
Bei einigen vorsegmentierten Binär-Farbbildern z.B. bei einem Roten Legoteil mit Bohrungen, wird der Schatten in den Bohrungen als schwarze Pixeln bzw. "schwarzes Teil" erkannt. Dies bekommen wir mit folgender Algorithmus entfernt:
- Mit einer If-Abfrage wird festgestellt ob nach der Vorsegmentierung ein Binär-Bild für schwarzes Teil und mind. eins für ein Teil in anderer Farbe erkannt wurde.
- Falls Ja: werden die Binärbilder addiert, um wenige Pixel dilatiert (vergrößert), und anschließend geprüft ob das neue Bild nur einen zusammenhängenden Teil ergibt oder nicht:
- Falls Ja: dann wird das schwarze Binär-Bild verworfen, da es sich dort nur um Schatten handelt.
- Falls nicht: dann handelt es sich um zwei verschiedene Lego-Teile.
- Um zu verhindern, dass die nicht optimal ausgeleuchtete Bereiche z.B. an einem grauen Legoteil als Dunkelgrau erkannt wird, wird folgendes durchgeführt:
- If-Abfrage ob es z.B. ein graues und ein dunkelgraues Binärbild erkannt wurde:
- Falls Ja: Summe der beiden bilden
- Prüfen ob die Summe nur einen Zusammenhängenden Teil ergibt, falls Ja: dann handelt es sich nur um einen (helleren) Teil, falls nicht --> zwei verschiedene Teile.
- Falls zwei verschiedene Teile erkannt wurden inkl. Schatten, dann wird durch Kombination von erst Summe und dann Differenz der Schatten herausgefiltert.
- If-Abfrage ob es z.B. ein graues und ein dunkelgraues Binärbild erkannt wurde:
Segmentierung:
- imclearborder: entfernt Rausch-Pixel an den Rändern
- bwareaopen: entfernt Segmente deren Pixelanzahl unter einem vorgegebenen Wert sind. (Salt&Pepper, Rauschunterdrückung)
- Bwlabel: die Summe aller Binärbilder werden Separiert und mit einem "Label" versehen.
Merkmalsextraktion:
- Merkmalsberechnung_3:
- Umfang, Fläche, Schwerpunkt, max. "Radius", min. "Radius"
Nachdem die Pixelfläche vom erkannten Teil berechnet wurde, wird solange iteriert, bis der Pixelflächenschwerpunkt in einem mittleren Kamerabild-Bereich befindet. Erst dann wird das Teil als Erkannt notiert.
Da das mittlere Bereich im Kamerabild nicht nur aus einer Pixelspalte besteht, wurde noch ein weiteres Kriterium abgefragt, um das selbe Teil nicht doppelt zu zählen:
- die Höhe (Y-Wert) von der Pixelflächenschwerpunkt der zuletzt erkannten Teil gespeichert und mit dem nächst erkannten Teil vergliechen, falls bestimmter Differenz überschritten wird --> dann handelt es sich um ein anderes Teil. Falls nicht --> das selbe Teil, wird nicht gezählt.
Der Kamerabildbereich wurde nicht als eine Pixelspalte mit der Breite von nur einem Pixel gewählt, da dadurch es schwieriger wurde, einen Pixelflächenschwerpunkt von einem erkannten Teil genau in dieser Pixelspalte zu erwischen.
Falls ein Teil erkannt (nicht doppelt):
- dann wird die Binärbild-Matrix an die Funktion "FARBERKENNUNG_V2" übergegeben, wo es zur einer nächstegelegener Legofarbe zugeordnet wird.
- Arduino wird signalisiert, dass in diesen Zeitpunkt ein Teil erkannt wurde, anhand der konstanten Bandgeschwindigkeit wird dann der Auswerfer angesteuert.
- Funktion imfindcircles: ermittelt Kreise als Merkmal im Binärbild.
Anschließend werden die ermittelten Merkmale mit Datenbank abgeglichen. Bei Übereinstimmung mit vordefinierten Toleranzen wird ein eindeutiges ID in einer Liste gespeichert.
Falls die "Escape"-Taste betätigt wird:
- dann werden wird die Schleife unterbrochen
- Arduino wird signalisiert um Laufbänder zu stoppen
- eine Liste der erkannten und fehlenden Teile wird als Excel automatisch geöffnet.
Quellcode Matlab:https://svn.hshl.de/svn/MTR_SDE_Praktikum_2015/trunk/SRC\Bildverarbeitung\Tracking\Algorithmus und Module\AutomatischesZaehlen.m
Farberkennung
Die Funktion "FARBERKENNUNG_V2" bekommt als Übergabewerte zwei Matrizen:
- Original-Frame (Farbbild) und Binärbild vom erkannten Teil
- mit Hilfe der Übergabeparametern wird eine 3D-Farbmaske erstellt (3D --> RGB).
- Farbmaske: Aus dem Originalbild werden nur die Pixeln in die Masken übernommen, die sich im Bereich vom Binärbild befinden
- Anschließend werden Mittelwerte für Rot, Grün und Blau berechnet.
Zuordnung zum nächstgelegener Farbe:
- Es werden die ermittelten RGB-Mittelwerte mit der Farbtabelle verglichen:
- zu erst werden die Differenzen von jeder Farbanteil zur der Farbtabelle ermittelt, und davon die maximalen werte gespeichert. z.B.: Die aktuelle Farbe (vom Legoteil) hat die maximale Abweichung im Farbanteil Rot zur Farbe Weis aus der Farbtabelle, max. Abw. im G zur Farbe Schwarz aus der Farbtabelle usw.
- Anschließend wird das minimalste Wert von den Maximalen Abweichungen ermittelt --> Es wird genau die Farbe ermittelt, welches die kleinste Abweichung zu der Legoteil-Farbe hat.
- Zum Schluss wird die ermittelte Farbe als String zurückgegeben.
Quelcode MATLAB:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Funktion : Merkmalsextraktion: FARBERKENNUNG %
% Autor : Christo Tsibadze %
% Implementation : MATLAB R2016a %
% %
% Funkion : Die Funktion ermittelt die Farbe von dem Überlagerten %
% Bereich aus Binär_Objekt_Bild und Originalbild und %
% ermittelt zu welcher Farbe der Tabelle am besten %
% ähnelt %
% EINGABE : RGB_BILD (:,:,3) in uint8 Format %
% BW_OBJECT(:,:) in Binärformat %
% AUSGABE : FARBE LEGO-Farbe als string %
% Änderungsdatum : 21.06.2016 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ FARBE ] = FARBERKENNUNG_V2( RGB_BILD, BW_OBJECT )
%% Farbwerte-Tabelle mit normierten Lego-Farben
% % R(1) G(1) B(1) Farbcode R(255) G(255) B(255)
Farbwerte=[ 1.00 1.00 1.00;% 01 255 255 255; %'weiss' 1
0.87 0.78 0.61;% 05 222 198 156; %'beige' 2
0.70 0.00 0.02;% 21 179 0 6; %'rot' 3
0.00 0.34 0.65;% 23 0 87 166; %'blau' 4
0.97 0.82 0.09;% 24 247 209 23; %'gelb' 5
0.13 0.13 0.13;% 26 33 33 33; %'schwarz' 6
0.06 0.80 0.19;% 37 16 203 49; %'gruen' 7
0.70 0.33 0.03;% 38 179 84 8; %'hellbraun' 8 % wird zurzeit nicht verwendet
% 0.69 0.71 0.78;% 194 175 181 199; %'hell-grau' 9
0.71 0.73 0.80;% 194 175 181 199; %'hell-grau' 9 %angepasst
% 0.35 0.36 0.38;% 199 89 93 96; %'dunkel-grau' 10
0.45 0.46 0.48;% 199 89 93 96; %'dunkel-grau' 10 %angepasst
0.20 0.00 0.00;% 308 51 0 0; %'dunkelbraun' 11 %wird zurzeit nicht verwendet
];
%% Eine Maske für die Farbextrahierung aus Binärbild erzeugen
[Hoehe, Breite]=size(BW_OBJECT); %Hoehe und Breite des Bildes ermitteln
Farbmaske=zeros(Hoehe, Breite, 3); %Null-Matrix für Farbmaske erstellen
RGB_BILD=im2double(RGB_BILD); %in double umwandeln, besser zu rechnen
BW_BILD=im2double(BW_OBJECT);
%% nur die Farben aus übereinstimmenden Pixeln RGB zu BW in der Farbmaske übernehmen
Farbmaske(:,:,1) = RGB_BILD(:,:,1).*BW_BILD(:,:); %für Rot
Farbmaske(:,:,2) = RGB_BILD(:,:,2).*BW_BILD(:,:); %für Grün
Farbmaske(:,:,3) = RGB_BILD(:,:,3).*BW_BILD(:,:); %für Blau
%% Pixel-Fläche des Binärbildes berechnen für die Mittelwertbildung
Pixel_Flaeche = sum(sum(BW_OBJECT)); %Flächenberechnung, Pixelanzahl
%% Mittelwertwerte für R, G und Blau berechnen
FARBE(1,1) = (sum(sum(Farbmaske(:,:,1))))/Pixel_Flaeche; %für jede Farbe Summe im Bild bilden und durch die Anzahl der Pixel teilen
FARBE(1,2) = (sum(sum(Farbmaske(:,:,2))))/Pixel_Flaeche;
FARBE(1,3) = (sum(sum(Farbmaske(:,:,3))))/Pixel_Flaeche;
%% Die Farbe aus der Tabelle mit geringster Abweichung zu aktueller Farbe bestimmen
% 1) zu Jeder Tabellenfarbe wird der größstabweichender Farbanteil der
% aktuellen Farbe ermittelt und gespeichert
% 2) anschließend wird die Farbe mit geringsten Wert von den
% maximalabweichungen ermittelt
temp = max(abs(Farbwerte(1,:)-FARBE)); % Max von R,G,B Differenzen zu erster Farbe
MIN_Diff=1;
for i=2:11
if(temp>(max(abs(Farbwerte(i,:)-FARBE)))) % falls der gleiche Wert mit anderer Farbe kleiner ist, speichern
MIN_Diff = i; % den Farbenindex mit kleinst. Abweichung speichern
temp=max(abs(Farbwerte(i,:)-FARBE));
end;
end
%% Farbenzuordnung FARBE als Rückgabe
% Anhand der gespeicherten Farbindex, wird eine Farbe zurückgegeben
% zurückgegeben
switch MIN_Diff
case 1
FARBE='weiss';
case 2
FARBE='beige';
case 3
FARBE='rot';
case 4
FARBE='blau';
case 5
FARBE='gelb';
case 6
FARBE='schwarz';
case 7
FARBE='gruen';
case 8
FARBE=38;
case 9
FARBE='hell-grau';
case 10
FARBE='dunkel-grau';
case 11
FARBE=308;
otherwise
%disp('Fehler')
%hier ist noch ein Zusatzfall unterscheidbar, es ist gedacht einen
%Maximalabweichung in der Berechnung einzubeziehen, falls die
%kleinst ermittelte Abweichung größer ist als ein bestimmter
%Grenzwert, dann soll hier Fehler ausgegeben werden.
end
end
Merkmale
UNTER BEARBEITUNG
Teach-IN
Zur Ermittlung von Merkmals-Daten für die einzelnen Legoteilen, wurde die Funktion Main (Bildverarbeitung) kurzzeitig modifiziert, so dass die Daten der Merkmale 10 Mal ermittelt wurden und anschließend daraus Mittelwerte berechnet wurden. Während der Datensammlung wurde jedes Legoteil einzeln 10 Mal nacheinander in die Bilderkennungsbox durchgefahren.
Automatisches Teach-IN mit GUI-Anbindung wurde für das kommende Semester vorgesehen.
Datenbankanbindung, Listen IN/OUT
Datenbank
Die Datenbank ist in MySQL implementiert und eine Verbindung mit Matlab wurde realisiert. Hinzukommt das alle Daten im Excel-Format vorhanden sind. Die Daten sind aufgeteilt in drei Excel Dateien, "Datenbank Teile-Kopie_fuer sql.xlsx", "Datenbank Kastendetails.xlsx", "Datenbank Kasten.xlsx", die die gesamte Datenbank representieren und alle einträge beinhaltet. Dies dient der Datensicherheit, da die Daten in getrennten Formaten und Speichermedien vorhanden sind. Die Struktur innerhalb der Tabellen sollte erhalten bleiben, aber die Daten innerhalb der Tupel können nach belieben manipuliert werden. In der Datei "InventurlisteErstellen_SQL.m" befindet sich ein Code, der die Daten in die gestartete SQL-Datenbank importieren kann. Dies ist aber nur möglich solange die Strucktur, Spaltennamen und Anzahl, bestehen bleibt.
Die Datenbank ist aufgeteilt in drei Tabellen, Legoteileliste, beinhaltet alle einzelnen Legoteile, Kastendetails, enthält die Nummer der Legokästen, und der Kasten Tabelle, die die Legoteile mit den Kästen verbindet. In der Tabelle Legoteileliste sollen alle Legoteile aufgenommen werden. Die Attribute für die Legoteile sind:
* DataID, der Primarykey, ist als Autoincrement implementiert und versieht jedes neu hinzugefügte Legoteil automatisch mit einer eindeutigen ID * LegoteileID, entspricht der ID vom Hersteller Lego, kann in unserer Datenbank zweimal vorkommen, wenn das Legoteil mehrere Perspektiven hat * Bezeichnung, eine kurze Beschreibung des Legoteils, eine eindeutige Beschreibung wurde mit zurhilfenahme von Onlineshops realisiert (max. 30 charakter lang) * Farbe, die Farbe des Bauteils nach Hersteller Norm * Form, noch in Bearbeitung * Umfang, der Pixelumfang vom Teach-In Prozess * Flaeche, der Flaecheninhalt des Legoteils in Pixel vom Teach-In Prozess * MaxSchwerpunkt, der maximale Schwerpunkt vom Teach-In Prozess * MinSchwerpunkt, der minimale Schwerpuntk vom Teach-In Prozess * Rundloch, entspricht der Anzahl der vom Teach-In Prozess erkannten Löcher im Legoteil * AnzPerspektiven, gibt die gesamt Anzahl aller vorhandenen Perspektiven, unterschiedliche Lagen eines einzelnen Legoteils, die neue Werte für die oben genannten Attribute liefert, an * Scanbar, '1' oder '0', '1' bedeutet es kann von der Legoteil Zählmaschine erkannt werden, '0' bedeutet es muss manuell, per Hand, gezählt werden, zB. weil es zu groß ist
Die Tabelle Kastendetails besteht aus:
* KastenID, der Primarykey, die vom Hersteller Lego vorgesehene Kastennummer, muss eindeutig sein * Bezeichnung, eine kurze Beschreibeung des Kasten bzw. den Namen des Kastens (max. 50 charakter lang)
Zu letzt die Tabelle Kasten, diese setzt sich zusammen aus einer LegoteileID, KastenID und Anzahl. Die Tabelle Kasten spiegelt die reale Welt wieder indem sie genau beschreibt welches Legoteil in welchem Kasten ist und wie oft dieses Legoteil in einem Kasten vorhanden ist:
* LegoteileID, Primarykey mit KastenID, Forenkey auf Legoteileliste.LegoteileID, dementsprechend eine ID aus Legoteileliste, (LegoteileIDs können nur zugewiesen werden wenn ein eintrag in Legoteileliste vorhanden ist) * KastenID, Primarykey mit LegoteileID, Forenkey auf Kastendetails.KastenID, dementsprechend eine ID aus Kastendetails, (KastenIDs können nur zugewiesen werden wenn ein eintrag in Legoteileliste vorhanden ist) * Anzhal, die genaue Anzahl eines Legoteil in einem bestimmten Kasten entnommen von der Originalverpackung von Lego (max. vierstelliger Integer wert)
Um in Matlab auf die Zugriff auf die Datenbank zu haben muss XAMPP und der MySQL ODBC - Connector installiert und konfiguriert sein. Sobald dies geschehen ist, kann mit:
DatenbankVerbindung = database.ODBCConnection('Lego','root','');
eine Verbindung hergestellt werden. Danach kann man mit mit SQL Befehlen Daten aus der Datenbank extrahieren und einpflegen. Ein Beispiel:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Es werden alle in der Datenbank enthaltenen Kaesten mit ID und Ihrer
% Bezeichnung als Stringarray zurueckgegeben
%
% conn = Verbindung zur Datenbank (ODBCConnection in der Regel
% database.ODBCConnection('Lego','root','') )
%
% alleKaesten = enthaelt alle Dateneintraege aus der Tabelle
% Kastendetails. In der Form ['ID - Bezeichnung'] als
% Stringarray
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function alleKaesten = getAllKasten(conn)
sqlquery = 'SELECT * FROM kastendetails';
curs = exec(conn, sqlquery);
curs = fetch(curs);
alleKaesten = cell(length(curs.Data),1);
for i = 1:1:length(curs.Data)
alleKaesten{i} = [num2str(curs.Data{i,1}) ' - ' curs.Data{i,2}];
end
end
In sqlquery wird der SQL-Befehl hinterlegt und mit exec(conn, sqlquery) wird der Befehl auf der Datenbank, die in conn spezifiziert ist, ausgeführt. Mit fetch(curs) wird das Ergebnis der SQL-Anfrage zurück gegeben, alles weitere ist eine manipulation der Struktur in der die Daten weitergeben werden sollen.
Installation der Datenbank
Für die Benutzung der Datenbank auf einem neun PC, müssen einige Dateien Installiert und Matlab Konfiguriert. Eine Schritt für Schritt Anleitung findet sich in der Dokumentation->Matlab->Einrichten der Datenbank.docx. Hier folgt eine Kurzanleitung anhand der Schritt für Schritt Anleitung:
1. Download von XAMPP und MySQL ODBC - Connector 2. Installation von XAMPP und MySQL ODBC - Connector 3. Starte XAMPP -> starte Apache -> starte MySQL 4. Erstelle eine neue Datenbank (Benenne die Datenbank, so das sie eindeutig und ihren nutzen klar werden lässt) 5. Konfiguration von Matlab 5.1 Im oberen Reiter auf APPS gehen 5.2 Wähle unter den APPS den Database Explorer 5.3 Gehe im Menu auf New->ODBC - Configure ODBC data source 5.4 Füge als neue Datenquelle den MySQl ODBC Unicode Driver hinzu 5.5 Server Daten eingeben -> Name: Lego ; TCP/IP Server: 127.0.0.1 Port: 3306; User: root; Password: - (leer lassen); Database: eure erstellte Datenbank wählen 5.6 Alles bestätigen -> Verbidung hergestellt
Erstellung einer Inventurliste
Eine Anforderung an die Legoteil Zählmaschine ist, dass dem Anwender nach Abschluss des Zählprozesses eine Liste in Excel ausgegeben wird, in der die gezählten Teile und dessen Anzahl aufgelistet sind. Dazu wurde zunächst eine Funktion InventurlistenTamplateMultiKaesten.m geschrieben, die aus der Datenbank die Bauteile ausliest, die in dem ausgewählten Baukästen enthalten sind und diese in eine Excel-Liste schreibt. Als Übergabeparameter benötigt die Funktion die entsprechenden BaukastenIDs, einen Dateinamen für die Inventurliste und die entsprechende Verbindung zur Datenbank. Als Rückgabewert gilt ein Cell-Array, welches den Inhalt der Inventurliste in Excel enthält.
Die Funktion InventurlistenTamplateMultiKaesten.m ist wie folgt implementiert:
function InventurListeContent=InventurlistenTamplateMultiKaesten( BaukastenName, InventurlisteName, conn)
%Die Funktion richtet ein Template für die Erstellung der Inventurliste ein
% Sie liest die Inhalte des gewünschten Baukastens ein und trägt sie
% mit Ihrer Anzahl in eine Excel-Liste ein. Es kann angepasst werden ob
% die Daten aus der SQL-Datenbank stammen oder aus einer Exceldatei mit
% dem Namen des Baukastens im *.xls-Format.
% Parameter:
% BaukastenName: String mit dem Namen des zu zählenden Baukastens
% InventurlisteName: String mit dem Namen der Exceldatei mit der
% Inventurliste
% Conn: Adresse der SQL-DB, wenn == 0, dann wird eine Excelliste
% eingelesen
%
% Autor: Niklas Lingenauber
% Letzte Änderung: 13.05.2016
%% Variablen definieren %%
Header={'ID' 'Bezeichnung' 'Farbe' 'Soll-Anzahl'}; %Überschriften der Inventurliste definieren
ID=1; %an Baukasten-Datenbank anpassen
Bezeichnung=2; %an Baukasten-Datenbank anpassen
Farbe=3; %an Baukasten-Datenbank anpassen
Anzahl=4; %an Baukasten-Datenbank anpassen
%% Einlesen der benötigten Teile des Baukastens %%
if conn~=0 %aus einer SQL-Datenbank
InventurListeContent=Header; %Überschriften der Liste in erste Zeile
KaestenN=size(BaukastenName,1); %Anzahl der baukästen bestimmen
for i=1:KaestenN
%Auslesen der Baukästen aus der Datenbank
sqlquery = strcat(['SELECT Legoteileliste.LegoteileID, Legoteileliste.Bezeichnung,'...
'Legoteileliste.Farbe, Kasten.Anzahl FROM Legoteileliste, Kasten '...
'WHERE Kasten.kastenID =',num2str(BaukastenName(i)),...
' AND legoteileliste.LegoteileID = kasten.LegoteileID']); %Erstellung des SQL-Befehls
cursor = exec(conn, sqlquery);
cursor = fetch(cursor);
%Eintragen in die vorhandene Inventurliste
InventurListeContent=vertcat(InventurListeContent,cursor.Data); %Inhalte der Bauteil-IDs im Baukasten i unten anfügen
end
else %aus einer Excelliste
%Definieren von Spalten in der Excel-Version
BaukastenName=[BaukastenName '.xlsx']; %Namensergänzung solange Datenbank eine Excel-Date
% Auslesen aus Excel
raw=xlsread(BaukastenName,3); %vorrübergehend, später aus Datenbank
ContentID=raw(2:175,ID); %Inhalte der Bauteil-IDs im Baukasten
Elements=size(ContentID,1)+1; %Anzahl der Teile im Kasten
ContentBezeichnung=raw(2:Elements,Bezeichnung); %Bezeichnungen der Bauteile
ContentFarbe=raw(2:Elements,Farbe); %Farben der Bauteile
ContentAnzahl=raw(2:Elements,Anzahl); %Anzahl der jeweiligen Bauteile IM Baukasten
InventurListeContent=horzcat(ContentID,ContentBezeichnung, ContentFarbe, ContentAnzahl); %Spalten zusammenfügen
end
%% Entfernen einer alten Inventurliste
xls_check_if_open(InventurlisteName,'close');
if exist(InventurlisteName, 'file') == 2 %Existiert eine alte Liste
delete(InventurlisteName); %Löschen
end
%% Erstellung der Excelliste %%
xlswrite(InventurlisteName,InventurListeContent); %ExcelDatei erstellen
end
Nach der Erstellung des Templates werden die Gezählten IDs in die Liste eingetragen. Dazu wird der Inhalt des Templates nach den entsprechenden IDs durchsucht und die dazugehörige Anzahl notiert. Durch den Angleich voll Soll- und Ist-Anzahl der einzelnen Legoteile, wird außerdem eine Fehlteilliste erstellt, die dem Anwender anzeigt, welche Teile in welcher Häufigkeit fehlen. Die Funktion InventurlisteFuellen.m benötigt ebenfalls die entsprechenden BaukastenIDs, einen Dateinamen für die Inventurliste und die entsprechende Verbindung zur Datenbank als Übergabeparameter.Außerdem werden die gezählten Legoteil-IDs und dessen Anzahl benötigt. Als Rückgabewert gilt erneut der Inhalt der Excel-Liste.
Die Funktion InventurlisteFuellen.m ist wie folgt implementiert:
function InventurlisteFuellen( InventurlisteName, InventurListeContent, GezaehlteIDs, conn)
%Die Funktion füllt eine Inventurliste aus
% Die Funktion sucht in der Datei 'InventurlisteName' die Zeilen aus der
% Inventurliste raus in der die gleiche ID der Elemente der Gezählten
% IDs steht. Dann trägt es die Anzahl in die entsprechenden Spalten ein.
% Parameter:
% InventurlisteName: String mit dem Namen der Exceldatei mit der
% Inventurliste inkl. Format '*.xls'
% InventurListeContent: Inhalt des unausgefüllten BaukastenTemplates
% GezählteIDs: Matrix in der die IDs in der ersten Spalte und die
% Anzahl in der zweiten Spalte aufgeführt sind.
% conn: Addresse der SQL-DB, wenn ==0, dann wird bei Bauteilen, die
% nicht zum Kasten gehören ein Kommentar statt einer
% bezeichnung eingefügt
%
% Autor: Niklas Lingenauber
% Letzte Änderung: 13.05.2016
%% Variablen definieren %%
SpalteIstAnzahl='E'; %Spalte in der Excel, in der die Ist-Anzahl eingetragen wird
ID=1;
Bezeichnung=2;
Farbe=3;
SollAnzahl=4;
IstAnzahl=5;
Andere=0; %Anzahl der Bauteile, die nicht zum Baukasten gehören
Vorkommen=zeros(length(InventurListeContent)-1,1); %Füllt die Ist-Anzahl zunächst mit 0en auf, Zeigt die Anzahl der IDs an
AnzahlIDs=GezaehlteIDs(2:length(GezaehlteIDs),2); %Anzahl der jeweiligen IDs
GezaehlteIDs=GezaehlteIDs(2:length(GezaehlteIDs),1); %entfernen der Überschriften und Konvertierung in Matrix
BaukastenIDs=InventurListeContent(2:length(InventurListeContent),1); %IDs die im Baukasten auftreten
%% Anzahlen der IDs ermitteln %%
for i=1:length(GezaehlteIDs) %Alle gezählten IDs eintragen
SucheNach=GezaehlteIDs(i); %gesuchte ID als Zahl
Zeile=0; %Laufindex
gefunden=false; %Variable zur Erkennung ob ID gefunden
while Zeile<length(BaukastenIDs) && gefunden==false %solange nicht gefunden und nicht am Ende
Zeile=Zeile+1; %Laufindex erhöhen
if cell2mat(BaukastenIDs(Zeile)) == SucheNach %Wenn ID gefunden
gefunden=true; %Abbruchbedingung setzen
end
end
if gefunden==true % Wenn gefunden, dann in Cell-Array eintragen
Vorkommen(Zeile)=Vorkommen(Zeile)+AnzahlIDs(i); %Entsprechende Anzahl notieren
else %Wenn nicht ID und Anzahl merken
%kein Bestandteil des Baukastens. IDs müssen angefügt werden
Andere=Andere+1;
if conn~=0
sqlquery = strcat('SELECT Bezeichnung,Farbe FROM legoteileliste WHERE legoteileID = ' , num2str(GezaehlteIDs(i)));
cursor = exec(conn, sqlquery);
cursor = fetch(cursor);
daten(1)=cursor.Data(1); %Bezeichnung
daten(2)=cursor.Data(2); %Farbe
else
daten={'Zusätzlich','Farbe'}; %Bezeichnung und Farbe
end
ZusaetzlicheTeile(Andere,ID)=num2cell(GezaehlteIDs(i)); %ID eintragen
ZusaetzlicheTeile(Andere,Bezeichnung)=daten(1); %Bezeichnung eintragen
ZusaetzlicheTeile(Andere,Farbe)=daten(2); %Farbe eintragen
ZusaetzlicheTeile(Andere,SollAnzahl)=num2cell(0); %Soll-Anzahl eintragen; 0, da nicht im Baukasten erwartet
ZusaetzlicheTeile(Andere,IstAnzahl)=num2cell(AnzahlIDs(i)); %Ist-Anzahl eintragen
end
end
%% Eintragen in die Liste %%
Vorkommen=vertcat('Ist-Anzahl',num2cell(Vorkommen)); %Überschrift einfügen
xlswrite(InventurlisteName,Vorkommen,'',[SpalteIstAnzahl '1']); %Bauteile des Baukastens
if exist ('ZusaetzlicheTeile')==1
BeginnWeitererTeile=['A' num2str(size(BaukastenIDs,1)+2)];
xlswrite(InventurlisteName,ZusaetzlicheTeile,'',BeginnWeitererTeile); %Anpassen
end
%% Fehlteilliste erstellen %%
SpalteDifferenz=6; %Anpassen, SpaltenNummer mit der zu bestllenden Differenz
FehlteillisteName='Fehlteile.xls'; %Anpassen, Name der Excel-Datei
InventurListeContent= horzcat(InventurListeContent,Vorkommen); %Anzahlen der IDs zur Inventurliste hinzufügen
FehlendeID=0; %Anzahl der nicht gezählten BauteilIDs, zunächst 0 annehmen
for i=1:length(InventurListeContent) %Liste durchsuchen
Differenz=InventurListeContent(i,4)-InventurListeContent(i,5); %Differenz bestimmen
if Differenz>0 %Wenn Teile fehlen
FehlendeID=FehlendeID+1; %Anzahl nicht gezählter IDs erhöhen
Fehlteile(FehlendeID)= InventurListeContent(i); %Inhalte merken
Fehlteile(FehlendeID,6)=Differenz; %Differenz eintragen
end
end
Fehlteile=vertcat({'ID','Fehlteile'},num2cell(Fehlteile)); %Überschrift einfügen
%% Entfernen einer alten Fehlteilliste
xls_check_if_open(FehlteillisteName,'close');
if exist(FehlteillisteName, 'file') == 2 %Existiert eine alte Liste
delete(FehlteillisteName); %Löschen
end
xlswrite(FehlteillisteName,Fehlteile,''); %Liste Speichern
winopen(FehlteillisteName);
end
end
Separierung und Zentrierung der Legoteile
Teilezentrierung
Die provisorisch aus Holz gefertigte Teilezentrierung wurde mit fixierbarer Variante aus Aluminium ersetzt. An den Zentrierungskomponenten wurden elastische Kunststoffstreifen geklebt und anschließend an den Alu-Profilen vor der Bildverarbeitungsbox festgeschraubt.
Separierung
Die Separierung wurde mit Hilfe von Geschwindigkeitsdifferenzen an den Laufbandübergängen realisiert.
Je größer die Geschwindigkeitsdifferenzen, desto bessere Separierung ist möglich.
Aber die Bilderkennung fungiert in diesem Punkt als "Flaschenhals", wenn das letzte Laufband zu schnell dreht, dann werden weniger Teile erkannt. --> Somit wurden experimentell die optimalen Geschwindigkeiten für jedes Laufband separiert für die Optimale Separierung und Bilderkennung.
Elektronik und Sicherheit
Neues 24V Netzteil
Wie in den offenen Punkten aus dem Artikel Legoteil Zählmaschine 2015 beschrieben, benötigte die Lego Zählmaschine ein stärkeres Netzteil. Bei der Auslegung der Maschine wurde das Netzteil für die Versorgung der Bandmotoren zu klein dimensioniert und bei gleichzeitigem Anlaufen der Motoren ist es vorgekommen, dass das alte Netzteil mit einem maximalen Ausgangsstrom von 10 A sich aus Selbsschutz abgeschaltet hat. Hier wurde ein stärkeeres Netzteil vom selben Hersteller mit 20 A maximalem Ausgangsstrom eingebaut. Dies besitzt eine etwas breite Bauweise, konnte aber durch leichte Änderungen im Schaltschrank installiert werden.
Kabelkanal
EBenfalls in den offenen Punkten des Artikels Legoteil Zählmaschine 2015 beschrieben, sollten die bisher provisorisch verlegten Leitungen fest verlegt werden. Hierzu wurde ein Kabelkanal zur ordentlichen Verlegung der Leitungen an den Förderbändern montiert. Er dient dem Schutz und der mechanischen Entlastung der Leitung. Es wurde ein geschlitzer Kabelkanal wewählt, da an vielen unterschiedlichen Stellen Leitungen z.B. zu den Motoren abgehen. So war es nicht nötig, einen geschlossenen Kabelkanal zu modifizieren, um die Leitungsabgänge möglich zu machen.
Kamera/Bildbox- und Auswerferhalterung
Die Bildbox und die Kamera waren bis zum jetzigen Zeitpunkt noch nicht befestigt und lagen lose auf dem Förderband auf. Dies barg die Gefahr, dass aus beide Teile aus ihrer beträchtlichen Höhe immer drohten herunterzufallen und irreperabel beschädigt zu werden. Zur Befestigung wurde "Boschprofil" mit den Zubehörwinkeln genutzt. Die Bildbox wurde so befestigt, dass sie über 4 Schrauben Höhenverstellbar ist, um auch die Einfuhr von größeren Teilen möglich zu machen. Ebenso ist die Befestigung am Förderband mit 4 Schrauben zu lösen und damit die gesamte Konstruktion verschiebbar. Die Kamera wurde an der Bildboxbefestigung so fixiert, dass sie bei dieser Höhen- und Seitenverstellung immer an der selben Stelle verharrt. Dies ermöglicht eine ein mal eingestellte Kameraposition beizubehalten. Ebenso wurde der Auswerfer am Ende des letzten Förderbandes mit Boschprofil und Winkeln befestigt. Somit ist die bisherige Befestigung über eine Holzkiste ersetzt worden.
Höhenanpassung der Laufbänder
An den Laufbandübergängen wurden verbesserungswürdige Fallhöhen festgestellt. Die Legoteile fallen von einem Laufband auf das andere, wenn die Fallhöhe zu groß ist, dann federn die Teile ab und fallen manchmal vom Band runter. Deshalb wurden die Höhen der Laufbänder so eingestellt, dass es kleinstmögliche Fallhöhen gibt. Ebenso wurde damit der das Förderband steiler gestellt und somit die Vereinzelung der Legoteile leicht verbessert, da die größeren Teile im Bunker weniger Halt auf den Lamellen finden können und eher abrutschen.
Elektrische Sicherheit
Die elektrische Sicherheit des Schaltschrankes wurde im Zuge der Umbauarbeiten sichergestellt, indem alle Leitungen gegen spannungsfestere Leitungen vom Typ H07 bzw. H05 ausgetauscht wurden. So werden nun auch die Anforderungen nach VDE 0100-600 erfüllt. Eine Anlagenprüfung soll im nächsten Semester vorgenommen werden, wenn alle noch anstehenden Anlagenveränderungen vorgenommen wurden.
HSHL-Wiki-Dokumentation
Die HSHL-Wiki-Dokumentation wurde von der gesamten Gruppe bearbeitet. Jedes Themenabschnitt unterliegt der bereits oben genannten Verantwortlichkeiten.
Video-Anleitung
UNTER BEARBEITUNG
Projektplanung
UNTER BEARBEITUNG hier können wir Unterschiede nennen: was wir anfangs geplant hatten und was wir wegen Machbarkeit mit Genehmigung von Prof. Schneider abgeändert haben...
Pflichtenheft Dokumentation in DOORS
UNTER BEARBEITUNG "Link angeben wo Pflichtenheft gespeichert wurde."
Prozessvisualisierung mit Visio
Die Prozesse wurden mit Microsoft´s Visio dokumentiert.
Abbildung x: Übersicht des Gesamtprogramms | Abbildung x: Detailierte Sicht der Bildveraberbeitung | Abbildung x: Teilgebiet der Bildverarbeitung: Farberkennung im Detail |
QM-Tests
Wurde mit Genehmigung von Prof. Schneider auf das nächste Semester verlegt.
Auswerfer
UNTER BEARBEITUNG
z.B. Inbetriebnahme des vorhandenen Auswerfers
Planung der Aufgaben für das nächste Semester
Für das kommende Semester wurde anfangs geplant, eine Sortierungsanlage zu entwerfen und realisieren. Leider wurde festgestellt, dass ein größeres Problem bei der Vereinzelung von den Legoteilen besteht. Durch den "Flaschenhals"-Bilderkennung ist es unmöglich allein durch die Laufbandgeschwindigkeits-Differenzen alle Legoteile zu vereinzeln. Das erste Laufband, welches die Legoteile aus dem Bunker auf die nächste Laufband fördert, muss modifiziert werden damit nicht zu viele Teile auf einmal gefördert werden. Als eine der Hauptaufgaben für das nächste Semester wurde die Vereinzelung von Legoteilen vor der Bildverarbeitung festgelegt. Zusätzlich dazu noch andere Aufgaben aus dem Pflichtenheft.
Konzept für Sortieranlage
Da es ein Konzept bereits entworfen wurde, wird dieses hier auch dokumentiert (eventuell für zukünftige Aufgaben).
Gedacht ist ein durch einem Motor am Rand angetriebene (konstanter Geschwindigkeit) Scheibe mit Gummi- oder Filsbeschichtung (damit die Legoteile nicht abprallen). Welches auf mindestens drei freilaufende Räder mit einem Nut rotierbar gelagert wird. In der Mitte (feststehende runde Platte) soll dann die Verkabelung (entweder elektrische Leitungen für elektro Motoren, oder pneumatische Leitungen für pneumatischen Auswerfern) platziert werden, die entweder elektrischen oder pneumatischen Auswerfern versorgen. Radial zur drehender Scheibe werden Kisten angebracht mit passend gebogenen Führungsblechen (damit die Legoteile immer in die Kisten fallen).
Zum Öffnen des 3D-Modells vom Konzept, laden Sie bitte folgende frei erhältliche Software 3DXML-Player herunter und öffnen Sie die im SVN Sortieranlage.3dxml gespeicherte 3dxml-Datei.
Ergebnisse
Anleitung Programmstart
- Vorbereitung
- LED-Stecker anschließen
- Hauptstecker anschließen
- Hauptschalter betätigen
- Datenbank starten
- XAMPP control panel starten
- Apache Modul starten
- MySQL Modul starten
- Matlab Programm öffnen
- unter SVN\MTR_SDE_Praktikum_2015\SRC die main-datei öffnen
- Programm starten
- Baukasten in der GUI auswählen
- handgezählte Teile eintragen
- automatischer Zählprozess
- Motoren werden automatisch gestartet
- Kästen hinter das Förderband stellen
- Legoteile in den Bunker füllen
- Esc-Taste betätigen zur Beendigung des automatischen Zählprozess
- Motoren werden automatisch ausgeschaltet
- Inventurliste wird ausgegeben
Fazit
Abgeschlossene Punkte
- Neues 24 V Netzteil
- Software zur Bildverarbeitung (BV)
- Bauteileliste in Excel
- Zeit bis zur Servoöffnung: ???
- Kabelkanal montieren
- Kamerahalterung
- Bildverarbeitungskasten
- Teilezentrierung
- Hohenanpassung von Laufbänder
- WEITERE...!
Offene Punkte
- Bildverarbeitung --> Optimierung, bessere Erkennung der Teile, schnellere Erkennung
- Problemfarbe --> Schwarz
- Teilevereinzelung --> Es soll eine 100%-ige Vereinzelung der Teile vor dem Bildverarbeitungsbox möglich sein.
- Teach-In Einbindung in das GUI
- GUI Fertigstellung
- Gesamtsystem Optimierung --> Erkennung von 60 Teile pro Sekunde
- Videoanleitung
- Abschlusspräsentation
Dokumentation
SVN
Link zur Bildverarbeitungs-Software --> Algorithmus und Module