/// <summary> /// Convert the list of components in to a list of reels /// </summary> /// <param name="componentList">Components to distribute over the reels</param> /// <returns>List of reels with the components</returns> private static List <Reel> ComponentsToReels(List <PnpComponent> componentList, int speed) { List <Reel> tempReelList = new List <Reel>(); List <Reel> result = new List <Reel>(); while (componentList.Count != 0) { PnpComponent curComponent = componentList[0]; List <PnpComponent> matchingComponents = componentList.FindAll(comp_ => (comp_.Comment == curComponent.Comment) && (comp_.ManufacturerPartNumber == curComponent.ManufacturerPartNumber)); //Find all components of the same type (footprint and comment/value are the same) componentList.RemoveAll(comp => matchingComponents.Contains(comp)); Reel newReel = new Reel(matchingComponents, speed); //make a reel from the components tempReelList.Add(newReel); } while (tempReelList.Count != 0) { string manufacturerPartNumber = tempReelList[0].Components[0].ManufacturerPartNumber; //Find all matching footprints List <Reel> similarReels = tempReelList.FindAll(reel => reel.Components[0].ManufacturerPartNumber == manufacturerPartNumber); //make a list of all reels who share the footprint tempReelList.RemoveAll(reel => similarReels.Contains(reel)); Footprint reelFootprint = DatabaseOperations.GetFootprint(manufacturerPartNumber); if (reelFootprint != null) { foreach (Reel reel in similarReels) { reel.Footprint = reelFootprint; } } result.AddRange(similarReels); } return(result); }
/// <summary> /// Returns a string to save the PNPcomponents of the reels in the reelList /// </summary> /// <param name="reelList">List of all reels with the components to save</param> /// <param name="included">Is the reel scheduled to be placed in the stacks</param> /// <returns>String that represents the components in the savefile</returns> private static string SaveStringComponents(List <Reel> reelList, bool included) { StringBuilder sbResult = new StringBuilder(); //TO DO: make foreach for (int reelIndex = 0; reelIndex < reelList.Count; reelIndex++) { List <PnpComponent> componentList = reelList[reelIndex].Components; for (int componentIndex = 0; componentIndex < componentList.Count; componentIndex++) { PnpComponent component = componentList[componentIndex]; sbResult.AppendFormat("Designator={0},manufacturer part number={1},X={2},Y={3},Rotation={4},Layer={5},comment={6},include={7}{8}", new object[] { component.Designator, component.ManufacturerPartNumber, component.Location.X, component.Location.Y, component.Location.Rotation, component.Location.Layer, component.Comment, included, Environment.NewLine }); } } return(sbResult.ToString()); }
/// <summary> /// Load a pick and place project from the project.path /// </summary> /// <param name="project">Project to load data to</param> /// <exception cref="PickAndPlace.FileOperationsException">Thrown when data is missing or when a line could not be decoded</exception> public static void LoadProject(PnpProject project) { List <PnpComponent> includedComponents = new List <PnpComponent>(); List <PnpComponent> excludedComponents = new List <PnpComponent>(); //project.stackListers = new List<StackList>(); using (StreamReader reader = new StreamReader(project.Path)) { while (!reader.EndOfStream) { string curLine = reader.ReadLine(); //# is a line with comment if (curLine.StartsWith("#") || String.IsNullOrWhiteSpace(curLine)) { continue; } string[] splitedLine = curLine.Split(new char[] { ',', '=' }, StringSplitOptions.None); switch (splitedLine[0]) { case "ProjectName": project.ProjectName = splitedLine[1]; break; case "ProjectFolder": project.ProjectFolder = splitedLine[1]; break; case "MachineType": project.Machine = (IMachine)Assembly.GetExecutingAssembly().CreateInstance(splitedLine[1]); project.Machine.DefaultSpeed = Convert.ToInt32(splitedLine[3]); for (int i = 5; i < splitedLine.Length; i++) { Nozzle nozzle = PNPconverterTools.StringToNozzle(splitedLine[i]); project.Machine.SetNozzle(i - 5, nozzle); } break; case "originOffsetX": project.HorizontalOriginOffset = float.Parse(splitedLine[1]); project.VerticalOriginOffset = float.Parse(splitedLine[3]); break; case "boardsX": project.BoardsX = Convert.ToInt32(splitedLine[1]); project.BoardsY = Convert.ToInt32(splitedLine[3]); break; case "distanceX": project.DistanceX = float.Parse(splitedLine[1]); project.DistanceY = float.Parse(splitedLine[3]); break; case "boardDimX": project.BoardWidth = float.Parse(splitedLine[1]); project.BoardLength = float.Parse(splitedLine[3]); break; case "Designator": //load new component string designator = splitedLine[1]; string manufacturerPartNumber_ = splitedLine[3]; float x = float.Parse(splitedLine[5]); float y = float.Parse(splitedLine[7]); int rotation = Convert.ToInt32(splitedLine[9]); Layer layer_; if (splitedLine[11] == Layer.Bottom.ToString()) { layer_ = Layer.Bottom; } else { layer_ = Layer.Top; } Location location_ = new Location(x, y, rotation, layer_); string comment = splitedLine[13]; bool included = Convert.ToBoolean(splitedLine[15]); PnpComponent comp = new PnpComponent(designator, location_, comment, manufacturerPartNumber_); if (included) { includedComponents.Add(comp); } else { excludedComponents.Add(comp); } break; case "Phase": //last part of the file string remainingLines = reader.ReadToEnd(); string[] remainingLinesSplited = remainingLines.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); //1) make reels from the components: project.IncludedReels = ComponentsToReels(includedComponents, project.Machine.DefaultSpeed); project.ExcludedReels = ComponentsToReels(excludedComponents, project.Machine.DefaultSpeed); List <Reel> completeReelList = new List <Reel>(project.IncludedReels); completeReelList.AddRange(project.ExcludedReels); //the completeReelList contains all reels, however these reels where not splited List <Reel> topReels, bottomReels; Reel.SplitReelList(completeReelList, out topReels, out bottomReels); completeReelList.Clear(); completeReelList.AddRange(topReels); completeReelList.AddRange(bottomReels); //topReels and bottomReels contain all reels, also the excluded reels //they will be reused later //2) read each line StackList newStackList = new StackList(project.Machine, Convert.ToInt32(splitedLine[1])); newStackList.Name = "stackList"; project.StackListers.Add(newStackList); int index = -1; for (int i = 0; i < remainingLinesSplited.Length; i++) { splitedLine = remainingLinesSplited[i].Split(new char[] { '=', ',' }); if (splitedLine[0] != "Phase") { index++; //Stacks are saved in order (starting at reel 0 -> reel n) string designator_ = splitedLine[1]; if (String.IsNullOrWhiteSpace(designator_)) { continue; //empty stack } bool locked = Convert.ToBoolean(splitedLine[5]); //find the reel in the completeReelList Reel matchingReel = completeReelList.Find(reel => reel.GetDesignators().Contains(designator_)); matchingReel.Speed = Convert.ToInt32(splitedLine[3]); newStackList.AddReel(matchingReel, locked, index); project.ReelsInStackList.Add(matchingReel); } else { //make a new phase //Phase=X (X=phase number) newStackList = new StackList(project.Machine, Convert.ToInt32(splitedLine[1])); newStackList.Name = "stackList"; project.StackListers.Add(newStackList); index = -1; } } //Reusing topReels and bottomReels Reel.SplitReelList(project.ReelsInStackList, out topReels, out bottomReels); project.TopReels = topReels; project.BottomReels = bottomReels; break; default: throw new FileOperationsException(String.Format("Unable to read file: {0}{2}Problem with reading folowing line:{2}{1}", project.Path, curLine, Environment.NewLine)); } } } if (project.StackListers.Count == 0) { //no phases saved project.IncludedReels = ComponentsToReels(includedComponents, project.Machine.DefaultSpeed); project.ExcludedReels = ComponentsToReels(excludedComponents, project.Machine.DefaultSpeed); } if ((project.HorizontalOriginOffset == -1f) || (project.VerticalOriginOffset == -1f) || (project.BoardsX == -1) || (project.BoardsY == -1) || (project.DistanceX == -1f) || (project.DistanceY == -1f) || (project.BoardWidth == -1f) || (project.BoardLength == -1f) || (project.Machine == null)) { throw new FileOperationsException("Not all data was found in the file"); } }
/// <summary> /// Reads both the pnpFile and the bom file and returns a list of reels based on the two files /// </summary> /// <param name="pnpFilePath">Path to the Pick and place file</param> /// <param name="pnpHeaders">Headers used to read the pnp file</param> /// <param name="bomFilePath">Path to the BOM file</param> /// <param name="bomHeaders">Headers used to read the BOM</param> /// <param name="defaultSpeed">Default speed of the reels</param> /// <returns>List of reels that was created based on the data in the files</returns> /// <exception cref="PickAndPlace.FileOperationsException">Thrown when some data cannot be processed </exception> /// <exception cref="PickAndPlace.HeaderNotFoundException">Thrown when one of the header parameters is not found</exception> /// <exception cref="PickAndPlace.PnpConversionException">Thrown when the pnp file uses an unknown length unit</exception> public static List <Reel> ReadPickAndPlaceFiles(string pnpFilePath, string[] pnpHeaders, string bomFilePath, string[] bomHeaders, int defaultSpeed) { List <Reel> result = new List <Reel>(); List <PnpComponent> components = new List <PnpComponent>(); using (StreamReader reader = new StreamReader(pnpFilePath, Encoding.Default)) { //I had the best result with Encoding.Default and Encoding.UTF7 (µ character) string line; string[] colNames; do { line = reader.ReadLine(); colNames = SplitLinePNPfile(line); } while (colNames.Length < pnpHeaders.Length); //find location of corresponding columns int colDesignator = IndexOfHeader(colNames, pnpHeaders[0]); int colX = IndexOfHeader(colNames, pnpHeaders[1]); int colY = IndexOfHeader(colNames, pnpHeaders[2]); int colLayer = IndexOfHeader(colNames, pnpHeaders[3]); int colRotation = IndexOfHeader(colNames, pnpHeaders[4]); int colComment = IndexOfHeader(colNames, pnpHeaders[5]); //read the document while (!reader.EndOfStream) { line = reader.ReadLine(); string[] parameters = SplitLinePNPfile(line); //first line is empty (contains "", so string.empty doesn't work) if (parameters.Length == colNames.Length) { float X, Y; int rotation; Layer layer = Layer.Top; X = ConvertPnpValue(parameters[colX]); Y = ConvertPnpValue(parameters[colY]); rotation = (int)Convert.ToDouble(parameters[colRotation]); switch (parameters[colLayer]) { case "B": case "BottomLayer": layer = Layer.Bottom; break; case "T": case "TopLayer": layer = Layer.Top; break; default: throw new FileOperationsException("Folowing line contains an unknown layer:" + Environment.NewLine + line); } Location loc = new Location(X, Y, rotation, layer); PnpComponent comp = new PnpComponent(parameters[colDesignator], loc, parameters[colComment]); components.Add(comp); } } } using (StreamReader xReader = new StreamReader(bomFilePath)) { string line = xReader.ReadLine(); string[] colNames = line.Split(','); //unlike the pnp file, the header of the BOM has no " "," " int colDesignators = IndexOfHeader(colNames, bomHeaders[0]); int colMPN = IndexOfHeader(colNames, bomHeaders[1]); int checkCounter = 0; while (!xReader.EndOfStream) { line = xReader.ReadLine(); string[] parameters = SplitLinePNPfile(line); if (parameters.Length == colNames.Length) { string[] designators = parameters[colDesignators].Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries); List <PnpComponent> bomComponents = new List <PnpComponent>(); foreach (string designator in designators) { PnpComponent comp = components.Find(comp_ => comp_.Designator == designator); if (comp == null) { throw new FileOperationsException("folowing designator was not found in the pick and place file: " + designator); } comp.ManufacturerPartNumber = parameters[colMPN]; bomComponents.Add(comp); checkCounter++; } Reel reel = new Reel(bomComponents, defaultSpeed); result.Add(reel); } } if (checkCounter != components.Count) { throw new FileOperationsException("The BOM contains more components then the Pick and Place file"); } } return(result); }
public void ExportToFile(string path, BoardSettings boardSettings, StackList phaseStackList) { StringBuilder sbStackOffset = new StringBuilder(); StringBuilder sbFeederSpacing = new StringBuilder(); StringBuilder sbComponentLocations = new StringBuilder(); int operationNumber = 1; int curSpeed = -1; for (int index = 0; index < this.totalAmountOfReels_; index++) { //values for when there is no reel float offsetX = 0; float offsetY = 0; string comment = ""; float feedSpacingReel = 0; Reel reelWithIntel = phaseStackList.GetReel(index); if (reelWithIntel != null) { Footprint reelsFootprint = reelWithIntel.Footprint; //this makes reading the code easier if (reelWithIntel.Footprint.StackType != StackType.Tray18mm) { offsetX = reelsFootprint.OffsetStackX; offsetY = reelsFootprint.OffsetStackY; } else { offsetX = -9.4f + reelsFootprint.Width / 2 + reelsFootprint.OffsetStackX; offsetY = 8.5f - reelsFootprint.Length / 2 + reelsFootprint.OffsetStackY; } comment = reelsFootprint.ManufacturerPartNumber; feedSpacingReel = reelsFootprint.FeedRate; int speedValue = reelWithIntel.Speed / 10; //1) check if the speed changes if (speedValue != curSpeed) { curSpeed = speedValue; sbComponentLocations.AppendFormat("0,{0},0,0,0,0,0,0,{1}", speedValue, Environment.NewLine); } //set all components for (int i = 0; i < reelWithIntel.Components.Count; i++) { PnpComponent comp = reelWithIntel.Components[i]; float distance; int nozzleNumber = this.GetNozzleNumber(reelsFootprint.Nozzle); //This should never give -1 and if it does, the machine wil give an error int compRotation; if (comp.Location.Layer == Layer.Top) { distance = comp.Location.Y; compRotation = ATmMachine.ConvertAngle(comp.Location.Rotation + reelsFootprint.Rotation); } else { //botom distance = boardSettings.BoardLength - comp.Location.Y; compRotation = ATmMachine.ConvertAngle(180 - (comp.Location.Rotation + reelsFootprint.Rotation)); } //%,Head,Stack,X,Y,R,H,skip,Ref,Comment, sbComponentLocations.AppendFormat("{0},{1},{2},{3:0.###},{4:0.###},{5},{6:0.##},0,{7},{8}{9}", new object[] { operationNumber, nozzleNumber, index, comp.Location.X, distance, compRotation, reelsFootprint.Height, comp.Designator, reelsFootprint.ManufacturerPartNumber, Environment.NewLine }); operationNumber++; } } //%,StackOffsetCommand,Stack,X,Y,Comment sbStackOffset.AppendFormat("65535,1,{0},{1},{2},{3}{4}", new object[] { index, offsetX, offsetY, comment, Environment.NewLine }); sbFeederSpacing.AppendFormat("65535,2,{0},{1},{2}", index, feedSpacingReel, Environment.NewLine); } using (StreamWriter writer = new StreamWriter(path)) { //1) origin offset writer.WriteLine("%,OriginOffsetCommand,X,Y,,"); writer.WriteLine("65535,0,{0:0.##},{1:0.##},", boardSettings.HorizontalOriginOffset, boardSettings.VerticalOriginOffset); writer.WriteLine(); //2) stack offset writer.WriteLine("%,StackOffsetCommand,Stack,X,Y,Comment"); writer.WriteLine(sbStackOffset.ToString()); //3) Feeder spacing writer.WriteLine("%,FeederSpacingCommand,Stack,FeedSpacing,"); writer.WriteLine(sbFeederSpacing.ToString()); //4) Board setup writer.WriteLine("%,JointedBoardCommand,X,Y,"); for (int i = 0; i < boardSettings.BoardsX; i++) { for (int j = 0; j < boardSettings.BoardsY; j++) { if ((i != 0) || (j != 0)) { //skip the first board float Xcoord = i * (boardSettings.BoardWidth + boardSettings.DistanceX); float Ycoord = j * (boardSettings.BoardLength + boardSettings.DistanceY); writer.WriteLine("65535,3,{0:0.##},{1:0.##},", Xcoord, Ycoord); } } } writer.WriteLine(); //5) Component locations writer.WriteLine("%,Head,Stack,X,Y,R,H,Skip,Ref,Comment,"); writer.Write(sbComponentLocations.ToString()); } }