component
MLX90614ESF-BCI-000-TU - 3 V Digital IR Thermometer, 5 deg FOV
Public Made by Adomby adom
Melexis MLX90614ESF-BCI-000-TU: factory-calibrated non-contact infrared thermometer, 3 V supply, 5 degree field of view (long collimator cap), gradient compensated, SMBus and PWM output, TO-39 4-lead can.
main
John Lauer
Add KiCad symbol and footprint, viewers, provenance, README, models.json and verification log
354b2dd
11h ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
#!/usr/bin/env python3
"""Overlay proof: the model rendered orthographically at the datasheet drawing's own scale, blended over the
Melexis MLX90614 datasheet Rev 021 p.49 Figure 45 (MLX90614xCI): side view and bottom view.
Red outline + blue fill = model silhouette; black = datasheet drawing.
usage: overlay.py model.step page49_400dpi.png out.png
Scale: 44.5 px/mm at 400 dpi, calibrated on the printed Ø9.00 (401 px) and 20.20 (899 px) dimensions.
"""
import sys
import numpy as np
import cadquery as cq
from PIL import Image, ImageDraw, ImageFilter, ImageChops, ImageFont
step, page, out = sys.argv[1:4]
K = 44.5
CX, CY, ZTOP = 2.54, 0.0, 20.58
SIDE_AXIS_X, SIDE_TOP_Y = 1616.5, 936.0 # drawing side view: can axis column, top row
BOT_C = (264 + 325 * 2944 / 2000, 654 + 413 * 2944 / 2000) # drawing bottom view centre (page px)
shape = cq.importers.importStep(step).val()
verts, tris = shape.tessellate(0.01, 0.2)
V = np.array([[v.x, v.y, v.z] for v in verts])
T = np.array(tris)
img = Image.open(page).convert('RGB')
W, H = img.size
def silhouette(proj):
m = Image.new('L', (W, H), 0)
d = ImageDraw.Draw(m)
P = proj(V)
for t in T:
d.polygon([tuple(P[i]) for i in t], fill=255)
return m
def side(Vv):
return np.stack([SIDE_AXIS_X + (Vv[:, 0] - CX) * K, SIDE_TOP_Y + (ZTOP - Vv[:, 2]) * K], 1)
def bottom(Vv):
dx, dy = Vv[:, 0] - CX, Vv[:, 1] - CY
u, v = dy, dx # mirror for the bottom view, then turn so the tab sits where Melexis drew it
return np.stack([BOT_C[0] + u * K, BOT_C[1] - v * K], 1)
def blend(mask, base):
fill = Image.new('RGB', (W, H), (60, 110, 255))
a = mask.point(lambda p: 70 if p else 0)
base = Image.composite(fill, base, a)
edge = ImageChops.subtract(mask.filter(ImageFilter.MaxFilter(5)), mask)
red = Image.new('RGB', (W, H), (230, 30, 30))
base = Image.composite(red, base, edge)
# keep the drawing's black lines on top
dark = img.convert('L').point(lambda p: 255 if p < 110 else 0)
return Image.composite(Image.new('RGB', (W, H), (0, 0, 0)), base, dark)
# bottom view: only the part below the header (leads cut at the seating plane, header, tab)
Vb = V.copy()
base = blend(silhouette(side), img)
base = blend(silhouette(bottom), base)
crop = base.crop((240, 640, 3230, 2560))
dr = ImageDraw.Draw(crop)
try:
f = ImageFont.truetype('DejaVuSans.ttf', 34)
except Exception:
f = ImageFont.load_default()
dr.text((20, 1870), 'Model (blue fill, red outline) over Melexis MLX90614 datasheet Rev 021 p.49 Figure 45 (xCI), 44.5 px/mm',
fill=(200, 20, 20), font=f)
crop.save(out)
print('OK', out, crop.size)