docs: Add component datasheets and update documentation

- Add datasheets for all components with an LCSC part number to doc/datasheets/
- Create README.md in datasheets directory explaining the download process
- Update CHANGELOGs and READMEs with information about the new datasheets
This commit is contained in:
2025-12-23 07:48:52 +01:00
parent b883bc6c7d
commit 34aecf7871
51 changed files with 251 additions and 1 deletions

7
.gitignore vendored
View File

@@ -58,4 +58,9 @@ fp-info-cache
# Cache files
project.kicad_sym
fp-lib-table
sym-lib-table
fabrication-toolkit-options.json
EWS.pdf
EWS.step
# Ignore venv directory
tools/venv/

View File

@@ -9,6 +9,9 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
## [Unreleased]
### Hinzugefügt
- **Dokumentation:** Datenblätter für alle Komponenten mit einer LCSC-Teilenummer in `doc/datasheets` hinzugefügt.
### Behoben
- **USB-Hub-Controller (U401/CH334):** Pin 4 (XO) auf GND gelegt, um den Betrieb ohne Kristall zu ermöglichen
- **DC/DC-Wandler (U202/XR76208):** Enable-Beschaltung von Spannungsteiler auf Zenerdiode geändert, um 12V-Betrieb zu ermöglichen

View File

@@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
### Added
- **Documentation:** Added datasheets for all components with an LCSC part number in `doc/datasheets`.
### Fixed
- **USB Hub Controller (U401/CH334):** Pin 4 (XO) connected to GND to enable operation without crystal
- **DC/DC Converter (U202/XR76208):** Enable circuit changed from voltage divider to Zener diode to enable 12V operation

View File

@@ -230,6 +230,7 @@ sensor_mcu: hat
## 📚 Weitere Ressourcen
- [Bauteil-Datenblätter](doc/datasheets/README.md)
- [Klipper Dokumentation](https://www.klipper3d.org/Config_Reference.html)
- [CAN-Bus Setup Guide](https://www.klipper3d.org/CANBUS.html)
- [Voron Documentation](https://docs.vorondesign.com/)

View File

@@ -230,6 +230,7 @@ sensor_mcu: hat
## 📚 Additional Resources
- [Component Datasheets](doc/datasheets/README.md)
- [Klipper Documentation](https://www.klipper3d.org/Config_Reference.html)
- [CAN-Bus Setup Guide](https://www.klipper3d.org/CANBUS.html)
- [Voron Documentation](https://docs.vorondesign.com/)

BIN
doc/datasheets/0402B102K500NT.pdf LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

BIN
doc/datasheets/0402WGF5101TCE.pdf LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

View File

@@ -0,0 +1 @@
0402WGF5101TCE.pdf

BIN
doc/datasheets/1N5819WS.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/AO3400A.pdf LFS Normal file

Binary file not shown.

Binary file not shown.

BIN
doc/datasheets/BZT52C15S.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/BZT52C4V7.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/CFS12V3T3R00.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/CFS12V3T5R0.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/CH334F.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/CJAC70P06.pdf LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
CL05A475MP5NRNC.pdf

Binary file not shown.

View File

@@ -0,0 +1 @@
CL05A475MP5NRNC.pdf

Binary file not shown.

View File

@@ -0,0 +1 @@
CL05A475MP5NRNC.pdf

View File

@@ -0,0 +1 @@
CL05A475MP5NRNC.pdf

View File

@@ -0,0 +1 @@
CL05A475MP5NRNC.pdf

BIN
doc/datasheets/KT-0805G.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/KT-0805Y.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/MDA1050-3R3M.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/PESD1CAN.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/README.md LFS Normal file

Binary file not shown.

BIN
doc/datasheets/RVT1H101M0607.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/SMAJ26A.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/SS56C.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/STM32G0B1KBU6.pdf LFS Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
doc/datasheets/USBLC6-2SC6.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/XC6206P332MR-G.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/XR76208ELTR-F.pdf LFS Normal file

Binary file not shown.

BIN
doc/datasheets/XT30PW-M30.G.Y.pdf LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1,135 @@
import csv
import os
import re
import time
import hashlib
import requests
from bs4 import BeautifulSoup
# --- Configuration ---
BOM_PATH = 'production/bom.csv'
OUTPUT_DIR = 'doc/datasheets'
PRODUCT_PAGE_URL = 'https://www.lcsc.com/product-detail/'
DATASHEET_BASE_URL = 'https://wmsc.lcsc.com/wmsc/upload/file/pdf/v2/'
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
}
# --- Helper Functions ---
def sanitize_filename(name):
"""Replaces characters that are invalid for filenames."""
return re.sub(r'[\\/*?:\"<>|]', '_', name)
def get_mfr_part_number(session, lcsc_part_number):
"""Fetches the product page and parses it for the Mfr. Part #."""
product_url = f"{PRODUCT_PAGE_URL}{lcsc_part_number}.html"
try:
response = session.get(product_url, timeout=15)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
mfr_title_cell = soup.find(lambda tag: tag.name == 'td' and 'Mfr. Part #' in tag.get_text(strip=True))
if mfr_title_cell:
mfr_value_cell = mfr_title_cell.find_next_sibling('td')
if mfr_value_cell and mfr_value_cell.find('span'):
return mfr_value_cell.find('span').text.strip()
except requests.exceptions.RequestException as e:
print(f" - ERROR: Could not fetch product page for {lcsc_part_number}. {e}")
except Exception as e:
print(f" - ERROR: Parsing Mfr. Part # failed for {lcsc_part_number}. {e}")
return None
def download_pdf(session, lcsc_part, mfr_part):
"""Downloads a PDF and saves it with the Mfr. Part #."""
pdf_url = f"{DATASHEET_BASE_URL}{lcsc_part}.pdf"
sanitized_mfr_part = sanitize_filename(mfr_part)
filepath = os.path.join(OUTPUT_DIR, f"{sanitized_mfr_part}.pdf")
if os.path.exists(filepath):
print(f" - INFO: File already exists for Mfr. Part '{mfr_part}'. Skipping.")
return filepath, True # Return path for deduplication check
print(f" - Downloading: {pdf_url}")
try:
pdf_response = session.get(pdf_url, timeout=60)
pdf_response.raise_for_status()
if 'application/pdf' in pdf_response.headers.get('Content-Type', ''):
with open(filepath, 'wb') as f:
f.write(pdf_response.content)
print(f" - SUCCESS: Saved to {filepath}")
return filepath, True
else:
print(f" - ERROR: URL did not return a PDF. Content-Type: {pdf_response.headers.get('Content-Type', 'N/A')}")
return None, False
except requests.exceptions.RequestException as e:
print(f" - ERROR: Could not download PDF for {lcsc_part}. {e}")
return None, False
def deduplicate_files():
"""Finds duplicate files in the output directory and replaces them with symlinks."""
print("\n--- Starting Deduplication Process ---")
hashes = {}
files_to_process = [f for f in os.listdir(OUTPUT_DIR) if f.endswith('.pdf')]
for filename in files_to_process:
filepath = os.path.join(OUTPUT_DIR, filename)
if os.path.islink(filepath):
continue
with open(filepath, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
if file_hash in hashes:
original_file = hashes[file_hash]
print(f" - DUPLICATE: '{filename}' is identical to '{os.path.basename(original_file)}'.")
os.remove(filepath)
# Create a relative symlink
relative_path = os.path.relpath(original_file, start=OUTPUT_DIR)
os.symlink(relative_path, filepath)
print(f" - ACTION: Replaced '{filename}' with a symbolic link.")
else:
hashes[file_hash] = filepath
print(f" - UNIQUE: '{filename}'")
print("--- Deduplication Finished ---")
# --- Main Execution ---
def main():
"""Main script execution."""
if not os.path.exists(BOM_PATH):
print(f"FATAL: BOM file not found at '{BOM_PATH}'")
return
os.makedirs(OUTPUT_DIR, exist_ok=True)
# --- Phase 1: Gather Info & Download ---
print("--- Starting Download Process ---")
download_tasks = {} # {lcsc_part: mfr_part}
with open(BOM_PATH, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
unique_lcsc_parts = {row.get('LCSC Part #', '').strip() for row in reader if row.get('LCSC Part #', '').strip()}
with requests.Session() as session:
session.headers.update(HEADERS)
for i, lcsc_part in enumerate(unique_lcsc_parts):
print(f"\nProcessing LCSC Part {i+1}/{len(unique_lcsc_parts)}: {lcsc_part}")
mfr_part = get_mfr_part_number(session, lcsc_part)
if mfr_part:
download_tasks[lcsc_part] = mfr_part
time.sleep(0.5) # Be a good citizen
print("\n--- All product information gathered. Starting downloads. ---")
for lcsc_part, mfr_part in download_tasks.items():
print(f"\nDownloading for LCSC Part: {lcsc_part} (Mfr: {mfr_part})")
download_pdf(session, lcsc_part, mfr_part)
time.sleep(0.5)
# --- Phase 2: Deduplicate ---
deduplicate_files()
print("\nScript finished.")
if __name__ == '__main__':
main()

2
tools/requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
requests
beautifulsoup4