2021-09-20 21:10:38 -06:00
|
|
|
|
import argparse
|
|
|
|
|
import pandas as pd
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
|
parser.add_argument("input", nargs="?", default=None)
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
2021-09-20 21:49:05 -06:00
|
|
|
|
|
2021-09-20 21:10:38 -06:00
|
|
|
|
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
|
2021-09-20 21:49:05 -06:00
|
|
|
|
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]]
|
|
|
|
|
|
2021-09-20 21:10:38 -06:00
|
|
|
|
|
|
|
|
|
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
|
2021-09-20 22:23:11 -06:00
|
|
|
|
args.input = "/home/brendan/Documents/tempsync/projects/0034_UniversalController/jlcparts.csv"
|
2021-09-20 21:10:38 -06:00
|
|
|
|
if args.input:
|
2021-09-20 22:23:11 -06:00
|
|
|
|
parts_csv = pd.read_csv(args.input, encoding_errors="replace", delimiter=",", index_col=False)
|
2021-09-20 21:10:38 -06:00
|
|
|
|
else:
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
logger.info("Parsing JLCPCB stock...")
|
|
|
|
|
|
2021-09-20 21:49:05 -06:00
|
|
|
|
stock = parts_csv[parts_csv["Stock"] > 0]
|
2021-09-20 21:10:38 -06:00
|
|
|
|
|
|
|
|
|
# NOTES:
|
|
|
|
|
# - if something has tolerance specified as absolute, "Value" may be wrong but "Tolerance" will be NA so it will be dropped
|
|
|
|
|
|
|
|
|
|
# resistors
|
2021-09-20 21:49:05 -06:00
|
|
|
|
resistors = stock[stock["First Category"] == "Resistors"].copy()
|
2021-09-20 22:23:11 -06:00
|
|
|
|
resistors["Value"] = resistors["Description"].str.extract(r"(\d+(\.\d+)?)<29><>").astype(float).iloc[:, 0]
|
|
|
|
|
resistors["Tolerance"] = resistors["Description"].str.extract(r"(\d+)%").astype(float) / 100
|
|
|
|
|
resistors["TempCoef"] = resistors["Description"].str.extract(r"(\d+)ppm/<2F><>").astype(float) / 1e6
|
2021-09-20 21:10:38 -06:00
|
|
|
|
power_frac = resistors["Description"].str.extract(r"(\d+)/(\d+)W").astype(float)
|
2021-09-20 21:49:05 -06:00
|
|
|
|
power_frac = power_frac.iloc[:, 0] / power_frac.iloc[:, 1]
|
2021-09-20 22:23:11 -06:00
|
|
|
|
power_dec = resistors["Description"].str.extract(r"(\d+(\.\d+))W").astype(float).iloc[:, 0]
|
2021-09-20 21:10:38 -06:00
|
|
|
|
power = power_frac.add(power_dec, fill_value=0)
|
|
|
|
|
power[power_frac.notnull() & power_dec.notnull()] = pd.NA
|
2021-09-20 21:49:05 -06:00
|
|
|
|
resistors["Power"] = power
|
|
|
|
|
resistors["Footprint"] = pd.NA
|
|
|
|
|
for fp, (pins, names) in footprints.items():
|
2021-09-20 21:10:38 -06:00
|
|
|
|
matches = False
|
2021-09-20 21:49:05 -06:00
|
|
|
|
for name in names:
|
|
|
|
|
matches = matches | (resistors["Package"] == name)
|
2021-09-20 21:10:38 -06:00
|
|
|
|
matches = matches & (resistors["Solder Joint"] == pins)
|
2021-09-20 21:49:05 -06:00
|
|
|
|
resistors.loc[matches, "Footprint"] = fp
|
2021-09-20 21:10:38 -06:00
|
|
|
|
# resistors.drop("Package", inplace=True)
|
|
|
|
|
resistors.dropna(inplace=True)
|
|
|
|
|
|
2021-09-20 21:49:05 -06:00
|
|
|
|
print(len(resistors))
|
|
|
|
|
|
2021-09-20 21:10:38 -06:00
|
|
|
|
# capacitors
|
2021-09-20 21:49:05 -06:00
|
|
|
|
capacitors = stock[stock["First Category"] == "Capacitors"].copy()
|
2021-09-20 21:10:38 -06:00
|
|
|
|
value = capacitors["Description"].str.extract(r"(\d+(\.\d+)?)([pnum]?)F")
|
2021-09-20 21:49:05 -06:00
|
|
|
|
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
|
2021-09-20 22:23:11 -06:00
|
|
|
|
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]
|
2021-09-20 21:10:38 -06:00
|
|
|
|
# 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)
|
2021-09-20 21:49:05 -06:00
|
|
|
|
capacitors.loc[matches, "Footprint"] = fp
|
2021-09-20 21:10:38 -06:00
|
|
|
|
# capacitors.drop("Package", inplace=True)
|
|
|
|
|
capacitors.dropna(inplace=True)
|
|
|
|
|
|
2021-09-20 21:49:05 -06:00
|
|
|
|
print(len(capacitors))
|
|
|
|
|
pass
|