#usage "Data generation for mounting machines\n" "

" "Generates files for smds on the top and bottom layers " "wich can be used with mounting machines. " "The x and y coordinates (units: mm) of the SMD elements are calculated " "as mean of maximum and mimimum value of the smds origin points. " "The calculated value does not necessarily fit with the origin " "point of the part in the layout." "All SMD elements populated in currently set assembly variant are considered." "

" "The syntax of the output data looks like this:" "

" "name x-coord y-coord rotation value package" "

" "Author: support@cadsoft.de" // THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED // 2019-09-20: Modified by D. Roosendaal to output a JLCPCB compatible CSV and BOM! // UNVERIFIED as of yet. Use at your own risk. // // *** YOU CAN POPULATE THIS LIST TO CORRECT ROTATION, AND TO [option] ADD SMT ORDER CODE // // Value, package, additional rotation (pos or neg), optional JLC SMT order code to populate the BOM string Modify[] = { "BC847B;SOT23-BEC;-90", "BC857B;SOT23-BEC;-90", "12.288MHz;ABM3B;-90", "BAV99;SOT-23;90", "LD117AS33TR;SOT223;-90", "BS170;SOT-23;90", "BSS84;SOT23;-90", "8V2;SOT23;-90", "S9012;SOT23-BEC;-90" }; // At this moment, JLCPCB seems to have a bug which stops properly reading of parts if one or more components have the optional order code. // This may or may not be useful to you in the future.... your decision. //"ADAU1701;LQFP-48;;C26394"}; if (board) board(B) { int NumParts=0; int i, j; string PartName[], PartValue[], PartPackage[]; int PartSorted[]; string List; string Code; // Get filename string fileName = dlgFileSave("Save File", filesetext(B.name, "CPL.csv"), "*.csv"); if (fileName == "") exit(0); output(fileName) { printf("Designator,Mid X,Mid Y,Layer,Rotation\n"); B.elements(E) if (E.populate) { int wasSmd, xmax =-2147483648, xmin = 2147483647, ymax = xmax, ymin = xmin; wasSmd = 0; E.package.contacts(C) { if (C.smd && C.smd.layer == 1) { wasSmd = 1; if (C.x > xmax) xmax = C.x; if (C.y > ymax) ymax = C.y; if (C.x < xmin) xmin = C.x; if (C.y < ymin) ymin = C.y; } } if (wasSmd) { i=0; // Look for the part&package in the Modify list, and apply rotation if applicable if (E.package.name==lookup(Modify, E.value, 1, ';')) { i=strtol(lookup(Modify, E.value, 2, ';')); } //Designator,Mid X,Mid Y,Layer,Rotation printf("%s,%5.3fmm,%5.3fmm,Top,%1.0f\n",E.name, u2mm((xmin + xmax)/2), u2mm((ymin + ymax)/2),E.angle+i); // Get part details to create the BOM, only populate parts that have a value. if(E.value) { PartSorted[NumParts]=0; PartName[NumParts]=E.name; PartValue[NumParts]=E.value; PartPackage[NumParts++]=E.package.name; } } } B.elements(E) if (E.populate) { int wasSmd, xmax =-2147483648, xmin = 2147483647, ymax = xmax, ymin = xmin; wasSmd = 0; E.package.contacts(C) { if (C.smd && C.smd.layer == 16) { wasSmd = 1; if (C.x > xmax) xmax = C.x; if (C.y > ymax) ymax = C.y; if (C.x < xmin) xmin = C.x; if (C.y < ymin) ymin = C.y; } } if (wasSmd) { i=0; // Look for the part&package in the Modify list, and apply rotation if applicable if (E.package.name==lookup(Modify, E.value, 1, ';')) { i=strtol(lookup(Modify, E.value, 2, ';')); } //Designator,Mid X,Mid Y,Layer,Rotation printf("%s,%5.3fmm,%5.3fmm,Bot,%1.0f\n",E.name, u2mm((xmin + xmax)/2), u2mm((ymin + ymax)/2),E.angle+i); // Get part details to create the BOM, only populate parts that have a value. if(E.value) { PartSorted[NumParts]=0; PartName[NumParts]=E.name; PartValue[NumParts]=E.value; PartPackage[NumParts++]=E.package.name; } } } } // Get filename for the BOM string fileNameBOM = dlgFileSave("Save File", filesetext(B.name, "BOM.csv"), "*.csv"); if (fileNameBOM == "") exit(0); output(fileNameBOM) { // Comment,Designator,Footprint - Comment being the value List+="Comment,Designator,Footprint\n"; for(i=0; i