import argparse import numpy as np import pandas as pd import re import logging logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) parser = argparse.ArgumentParser() parser.add_argument("input", nargs="?", default=None) args = parser.parse_args() def mlcc_code2specs(code): specs = {} code = code.lower() if code in ["c0g", "np0"]: # type 1 specs["temperature_min"] = -55 specs["temperature_max"] = +125 specs["tolerance"] = 0 else: # type 2 specs["temperature_min"] = { "x": -55, "y": -30, "z": +10, }[code[0]] specs["temperature_max"] = { 2: +45, 4: +65, 5: +85, 6: +105, 7: +125, }[int(code[1])] specs["tolerance"] = { "d": 0.033, "e": 0.047, "f": 0.075, "p": 0.10, "r": 0.15, "s": 0.22, "t": 0.33, "u": 0.56, "v": 0.82, }[code[2]] footprints = { "0402": (2, ["0402", "R0402", "C0402"]), "0603": (2, ["0603", "R0603", "C0603"]), "0805": (2, ["0805", "R0805", "C0805"]), "1206": (2, ["1206", "R1206", "C1206"]), "1210": (2, ["1210", "R1210", "C1210"]), "1218": (2, ["1218", "R1218", "C1218"]), "2512": (2, ["2512", "R2512", "C2512"]), } # TODO: remove hardcoded csv args.input = ( "/home/brendan/Documents/tempsync/projects/0034_UniversalController/jlcparts.csv" ) if args.input: parts_csv = pd.read_csv( args.input, encoding_errors="replace", delimiter=",", index_col=False ) else: raise NotImplementedError() logger.info("Parsing JLCPCB stock...") stock = parts_csv[parts_csv["Stock"] > 0] # NOTES: # - if something has tolerance specified as absolute, "Value" may be wrong but "Tolerance" will be NA so it will be dropped # resistors resistors = stock[stock["First Category"] == "Resistors"].copy() resistors["Value"] = ( resistors["Description"].str.extract(r"(\d+(\.\d+)?)��").astype(float).iloc[:, 0] ) resistors["Tolerance"] = ( resistors["Description"].str.extract(r"(\d+)%").astype(float) / 100 ) resistors["TempCoef"] = ( resistors["Description"].str.extract(r"(\d+)ppm/��").astype(float) / 1e6 ) power_frac = resistors["Description"].str.extract(r"(\d+)/(\d+)W").astype(float) power_frac = power_frac.iloc[:, 0] / power_frac.iloc[:, 1] power_dec = ( resistors["Description"].str.extract(r"(\d+(\.\d+))W").astype(float).iloc[:, 0] ) power = power_frac.add(power_dec, fill_value=0) power[power_frac.notnull() & power_dec.notnull()] = pd.NA resistors["Power"] = power resistors["Footprint"] = pd.NA for fp, (pins, names) in footprints.items(): matches = False for name in names: matches = matches | (resistors["Package"] == name) matches = matches & (resistors["Solder Joint"] == pins) resistors.loc[matches, "Footprint"] = fp # resistors.drop("Package", inplace=True) resistors.dropna(inplace=True) print(len(resistors)) # capacitors capacitors = stock[stock["First Category"] == "Capacitors"].copy() value = capacitors["Description"].str.extract(r"(\d+(\.\d+)?)([pnum]?)F") value = value.iloc[:, 0].astype(float) * value.iloc[:, 2].replace( ["p", "n", "u", "m", ""], [1e-12, 1e-9, 1e-6, 1e-3, 1] ).astype(float) capacitors["Value"] = value capacitors["Tolerance"] = ( capacitors["Description"].str.extract(r"(\d+)%").astype(float) / 100 ) capacitors["Voltage"] = ( capacitors["Description"].str.extract(r"(\d+(\.\d+)?)V").astype(float).iloc[:, 0] ) # TODO: "MLCC"/"Tantalum" code_np0 = capacitors["Description"].str.contains(r"NP0") code_t1 = capacitors["Description"].str.extract(r"([CBLAMPRSTVU][01234678][GHJKLMN])") code_t2 = capacitors["Description"].str.extract(r"([XYZ][24567][DEFPRSTUV])") code = code_t1 code[code_t2.notnull()] = code_t2 code[code_np0] = "C0G" capacitors["Code"] = code capacitors["Footprint"] = pd.NA for fp, (pins, name) in footprints.items(): matches = False for n in name: matches = matches | (capacitors["Package"] == n) matches = matches & (capacitors["Solder Joint"] == pins) capacitors.loc[matches, "Footprint"] = fp # capacitors.drop("Package", inplace=True) capacitors.dropna(inplace=True) print(len(capacitors)) pass