Osazovací přípravek

Ke mému článku o výrobě tišťáků v Číně včetně osazení přišlo do redakce Robodoupěte tisíce děkovných dopisů, za které čtenářům srdečně děkuji. Ve článku mimo jiné zmiňuji, že jsem k desce udělal osazovací přípravek pro snazší osazování konektorů a mnozí čtenáři se mě ptají, jak se to vlastně dělá. Tak tedy, přípravek jsem vymodeloval v OpenSCADu a vytiskl na 3D tiskárně a v tomto článku vám ve formě tutoriálu ukážu, jak na to, včetně triku, jak z Eaglu (ve kterém jsem vytvořil návrh desky) jednoduše vytáhnout souřadnice součástek.

Tento tutoriál předpokládá alespoň základní chuť použít modelovací nástroj OpenSCAD. Kdo ho neznáte, seznamte se s ním, je velice užitečný a docela jednoduchý (na Robodoupěti jsem o něm už několikrát povídal, slajdy naleznete ve fóru v tomto příspěvku). Začít s ním také není těžké, tento článek je zároveň i tak trochu tutoriálem na OpenSCAD.

Na Connector Shieldu pro Arduino Uno je 20 třípinových konektorů se zámkem Ninigi NS25-w3p1. Jsou ve třech řadách (dvě po 7 konektorech pro digitální a jedna s 6 pro analogové), analogové jsou oproti digitálním otočeny čelem vzad, aby se snadno odlišily. Konektory jsou zámkové, aby se předešlo zapojení obráceně2. Vzhledem k rozměrům je však možné do tohoto konektoru zapojovat i běžné „hřebínkové“ konektory nebo i jednotlivé piny označované SPK, Dupont apod.

Osazovací přípravek vypadá jako destička s dírama pro konektory, kam se ty konektory nastrkají, pak se na ně položí osazovaná deska a konektory se zapájejí. Má to několik výhod – za prvé budou všechny konektory hezky zarovnané3, za druhé jsou prohlubně pro konektory udělané tak, aby se konektor nedal vložit a připájet obráceně, a za třetí se usnadní manipulace při pájení, protože není potřeba konektor přidržovat.


V následujícím textu si nejprve popíšeme, jak se vymodeluje konektor, a následně jak se udělá celý přípravek (a v rámci toho vysvětlím i jak získat souřadnice součástek z návrhu desky v Eagle).

Část 1 – Model konektoru

Konektor Ninigi NS25-W3P jsem si nejprve vymodeloval podle jeho rozměrové specifikace z datasheetu.

Ninigi NS25-W3P

Není potřeba modelovat všechny detaily, například detaily spodku základny4, západku na zámku, zaoblení zámku nebo zkosení konců pinů. Stačí vymodelovat hlavní části, a to jsou 1. základna konektoru, 2. zámek, 3. piny.

Konektory se liší jen počtem pinů, takže si udělám modul5, který jako parametr dostane počet pinů a jeho výstupem bude patřičně velký konektor:

module connectorNS25_WNp(pins)
{
}

Nyní ty jednotlivé části:

1. Základna

Základna konektoru je zjednodušeně kvádřík („cube“), který má podle datasheetu rozměry 3,3 mm (výška), 2,54xN mm (šířka – 2,54-násobek počtu pinů), 5,8 mm (hloubka). Protože s rozměry budu pracovat opakovaně, přiřadil jsem si je do pojmenovaných proměnných a dále budu používat toto jméno:

module connectorNS25_WNp(pins)
{
  base_d=5.8;
  base_h=3.3;  
  base_w=2.54*pins;
  cube([base_w, base_d, base_h]); // base
}

Základna konektoru

2. Zámek

Zámek je zjednodušeně opět kvádřík, který je postavený na okraji základny konektoru (uprostřed delší strany). Jeho rozměry jsou 11,5 mínus 3,3 mm (výška6), 2,54x(N-1) mm (šířka) a 1,16 mm (hloubka7). Oproti rohu základny je posunutý v ose X o 1,27mm (od okraje doprostřed prvního pinu) a v ose Z o výšku základny:

lock_w=2.54*(pins-1);
lock_d=1.16;
lock_h=11,5-3,3;
translate([1.27, 0, base_h])
  cube([lock_w, lock_d, lock_h]); // lock

Základna konektoru + zámek

3. Piny

Piny budu modelovat také jako kvádříky s čtvercovým průřezem 0.64 mm a celkovou výškou 14.2 mm, posunuté vůči základně o 3,3 mm dolů (vše podle datasheetu). Piny vytvořím pomocí cyklu, kde v každé iteraci vytvořím jeden pin a posunu v ose X o 2,54-násobek pořadí pinu a v ose Y tak, aby umístění odpovídalo poloze na konektoru:

translate([1.27-pin_w/2, base_d/2-pin_w/2, 0])
  for(i=[0:1:pins-1])
    translate([i*2.54, 0, -3.3])
      cube([pin_w, pin_w, pin_h]); // pins

Základna + zámek + piny

Nakonec celý konektor posunu tak, aby souřadnice [0,0] ve vodorovné rovině odpovídaly středu prostředního pinu, protože konektor jako součástka v Eagle má souřadnice umístění právě tam. Při podrobné kontrole jsem také zjistil, že řada pinů není přesně ve středu konektoru, a proto jsem ji oproti ostatním částem posunul ještě o 0,3 mm8:

module connectorNS25_WNp(pins)
{
  base_w=2.54*pins;
  base_d=5.8;
  base_h=3.3;  
  lock_w=2.54*(pins-1);
  lock_d=1.16;
  lock_h=11.5-3.3;
  pin_w=0.64;
  pin_d_displacement=0.3;
  pin_h=14.2;
  
  translate([-pins/2*2.54, -(base_d/2+pin_d_displacement), 0]) 
  {
    // base
    cube([base_w, base_d, base_h]); 
    
    // lock
    translate([1.27,0,base_h])
      cube([lock_w, lock_d, lock_h]); 
    
    // pins
    translate([1.27-pin_w/2, base_d/2+pin_d_displacement-pin_w/2, 0])
      for(i=[0:1:pins-1])
        translate([i*2.54, 0, -3.3])
          cube([pin_w, pin_w, pin_h]); 
  }
}

Vycentrovaný konektor

Kvůli tomu posunu (translate) jsem musel definice některých hodnot přesunout nahoru, aby byly definované dřív, než je budu chtít právě v tom posunu použít. A aby kód nevypadal rozházeně, tak jsem je tam přesunul všechny.

Ještě jen tak pro kontrolu pohled zdola:

Pohled na konektor zdola

A pohled na několik konektorů vedle sebe (díky tomu, že modul na konektor dostane jako parametr počet pinů, se ty konektory liší jen tím, jak je zavolám; pro obrázek jsem je ještě posunul trochu od sebe, to je to translate před zavoláním modulu):

connectorNS25_WNp(2);
translate([3*2.54, 0, 0]) connectorNS25_WNp(3);
translate([7*2.54, 0, 0]) connectorNS25_WNp(4);
translate([12*2.54, 0, 0]) connectorNS25_WNp(5);

Několik konektorů vedle sebe

Část 2 – přípravek

1. Základ

Jak jsem napsal dříve, celý přípravek je v podstatě deska, ze které budou odebrané („odečtené“) konektory. Nejdřív zkusím jeden – udělám nějakou kostku a zasadím do ní konektor jen abych viděl, jak to vypadá:

difference()
{
  translate([-10, -10, 0])
    cube([20, 20, 20]);
  connectorNS25_WNp(3);
}

deska s odebraným konektorem, pohled zdola

2. Export souřadnic součástek z Eagle

Pokud máme navrženou desku v nějakém normálním návrhovém systému, určitě je vhodné získat souřadnice potřebných součástek přímo z něj něj automaticky. Můj „trik“, jak z Eaglu dostat souřadnice součástek je zde:
Jde to samozřejmě více způsoby, já jsem to vzal přímo z popisu desky (soubor s koncovkou .brd). Ten je už od verze Eagle asi tak 7 v textové podobě, je strukturovaný a docela dobře čitelný (dřív byl binární). Když si ho otevřu v textovém editoru, tak vyhledám sekci <elements>, kde jsou všechny součástky hezky pohromadě. V mém případě jsem tam viděl:

<elements>
<element name="ARDUINO" library="arduino" package="ARDUINO_DUEMILANOVE_4" value="ARDUINO_DUMILANOVE_FULL*" x="0" y="0"/>
<element name="J1" library="con-lstb" package="MA03-1LOCK" value="" x="59.055" y="27.94" rot="R90"/>
<element name="J2" library="con-lstb" package="MA03-1LOCK" value="" x="59.055" y="40.64" rot="R90"/>
<element name="J3" library="con-lstb" package="MA03-1LOCK" value="" x="49.8475" y="27.94" rot="R90"/>
<element name="J4" library="con-lstb" package="MA03-1LOCK" value="" x="49.8475" y="40.64" rot="R90"/>
<element name="J5" library="con-lstb" package="MA03-1LOCK" value="" x="40.64" y="27.94" rot="R90"/>
<element name="J6" library="con-lstb" package="MA03-1LOCK" value="" x="40.64" y="40.64" rot="R90"/>
<element name="J7" library="con-lstb" package="MA03-1LOCK" value="" x="31.4325" y="27.94" rot="R90"/>
<element name="J8" library="con-lstb" package="MA03-1LOCK" value="" x="31.4325" y="40.64" rot="R90"/>
<element name="J9" library="con-lstb" package="MA03-1LOCK" value="" x="22.225" y="27.94" rot="R90"/>
<element name="J10" library="con-lstb" package="MA03-1LOCK" value="" x="22.225" y="40.64" rot="R90"/>
<element name="J11" library="con-lstb" package="MA03-1LOCK" value="" x="13.0175" y="27.94" rot="R90"/>
<element name="J12" library="con-lstb" package="MA03-1LOCK" value="" x="13.0175" y="40.64" rot="R90"/>
<element name="J13" library="con-lstb" package="MA03-1LOCK" value="" x="3.81" y="27.94" rot="R90"/>
<element name="J14" library="con-lstb" package="MA03-1LOCK" value="" x="3.81" y="40.64" rot="R90"/>
<element name="J15" library="con-lstb" package="MA03-1LOCK" value="" x="13.0175" y="15.24" rot="R270"/>
<element name="J16" library="con-lstb" package="MA03-1LOCK" value="" x="22.225" y="15.24" rot="R270"/>
<element name="J17" library="con-lstb" package="MA03-1LOCK" value="" x="31.4325" y="15.24" rot="R270"/>
<element name="J18" library="con-lstb" package="MA03-1LOCK" value="" x="40.64" y="15.24" rot="R270"/>
<element name="J19" library="con-lstb" package="MA03-1LOCK" value="" x="49.8475" y="15.24" rot="R270"/>
<element name="J20" library="con-lstb" package="MA03-1LOCK" value="" x="59.055" y="15.24" rot="R270"/>
<element name="JP1" library="jumper" package="JP2" value="" x="5.3975" y="15.24" rot="R270"/>
<element name="R1" library="rcl" package="R0805" value="220" x="44.45" y="43.18" rot="MR0"/>
<element name="R2" library="rcl" package="R0805" value="220" x="35.2425" y="30.48" rot="MR0"/>
...

Mě budou zajímat jen součástky s názvem Jněco, protože tak se v mém schematu jmenují všechny konektory, a jak vidíme výše, souřadnice i natočení součástky tam jsou pěkně naservírované. Pro skript do OpenSCADu jsem z toho udělal pole:

connectors=[
[59.055, 27.94, 90],
[59.055, 40.64, 90],
[49.8475, 27.94, 90],
[49.8475, 40.64, 90],
[40.64, 27.94, 90],
[40.64, 40.64, 90],
[31.4325, 27.94, 90],
[31.4325, 40.64, 90],
[22.225, 27.94, 90],
[22.225, 40.64, 90],
[13.0175, 27.94, 90],
[13.0175, 40.64, 90],
[3.81, 27.94, 90],
[3.81, 40.64, 90],
[13.0175, 15.24, 270],
[22.225, 15.24, 270],
[31.4325, 15.24, 270],
[40.64, 15.24, 270],
[49.8475, 15.24, 270],
[59.055, 15.24, 270]
];

Získat potřebné pole souřadnic ze seznamu součástek je snadné; v mém oblíbeném UltraEdit to bylo jednoduché nahrazení pomocí regulárního výrazu, ale samozřejmě se to dá udělat třeba i ručně prostě promazáním a doplněním hranatých závorek a čárek9.

Doplnění: Na upozornění Fuldy z fóra dodávám ještě, že z editoru desek se v Eagle dá vyexportovat partlist, kde ty souřadnice jsou v textovém formátu10, a pak si z něj data pro OpenSCAD můžete udělat třeba i makrem v Excelu11. Jak jsem Fuldovu poznámku zkoumal, tak jsem plácnul „Ale co, napíšu si na to svůj ulp a bude“, a taky že jo: v Eaglu je k dispozici jazyk na psaní uživatelských skriptů (User Language Program, ULP) a v něm jsem napsal vlastní skript, který se v Eagle spustí a vyrobí přímo soubor s definicí pole pro OpenSCAD. Udělal jsem si tam i několik užitečných nastavení, která by se tím ručním kopírováním z .brd souboru nebo zpracováním vyexportovaného partlistu dělala nešikovně nebo udělat ani nedala, protože ne všechny informace v tom exportovaném souboru jsou (zatímco skript je má, protože si je může vzít zevnitř Eaglu):

Můj dialog pro export


To ^J\d v RegExp Pattern způsobí, že se budou exportovat součástky, co začínají na J a za tím J je nějaká cifra12.
connectors = [
// Date exported: 2021-05-15 12:45:14
// Board name: D:/temp.brd
// Exporting: top, THT 
// Selection pattern: ^J\d
// Units: milimeters
//[   x   ,   y   , rot ], // name | 
  [  59.05,  27.94,  90 ], // J1 | 
  [  59.05,  40.64,  90 ], // J2 | 
  [  49.85,  27.94,  90 ], // J3 | 
  [  49.85,  40.64,  90 ], // J4 | 
  [  40.64,  27.94,  90 ], // J5 | 
  [  40.64,  40.64,  90 ], // J6 | 
  [  31.43,  27.94,  90 ], // J7 | 
  [  31.43,  40.64,  90 ], // J8 | 
  [  22.23,  27.94,  90 ], // J9 | 
  [  22.23,  40.64,  90 ], // J10 | 
  [  13.02,  27.94,  90 ], // J11 | 
  [  13.02,  40.64,  90 ], // J12 | 
  [   3.81,  27.94,  90 ], // J13 | 
  [   3.81,  40.64,  90 ], // J14 | 
  [  13.02,  15.24, 270 ], // J15 | 
  [  22.23,  15.24, 270 ], // J16 | 
  [  31.43,  15.24, 270 ], // J17 | 
  [  40.64,  15.24, 270 ], // J18 | 
  [  49.85,  15.24, 270 ], // J19 | 
  [  59.05,  15.24, 270 ], // J20 | 
];

Nebylo to nijak složité napsat – je to jazyk céčkovitého typu plus v manuálu popsaný přístup ke všem prvkům z návrhu, takže to šlo snadno a rychle13. Ten můj skript si můžete volně stáhnout z Githubu: DavidOb/eagle2openscad a samozřemě upravit, jak chcete – kdo se nebojí programovat, snadno si tam doplní nebo změní, co potřebuje.

3. Odečtení konektorů od základové desky přípravku

Rozměry desky Arduino Uno jsou 68,6 mm x 53,3 mm, takže přípravek bude kvádr se stejnými rozměry základny14 a výšku jsem si zvolil 20 mm:

cube([68.6, 53.3, 20]);

Nebo hezčeji

box_w=68.6;
box_d=53.3;
box_h=20;
cube([box_w, box_d, box_h]);

Všechny konektory získám tak, že iterativně zpracuji všechny položky v poli:

for(i=connectors)           // v proměnné i dostanu vždycky jeden prvek pole connectors
  translate([i[0], i[1], 0])  // posunout na místo součástky na desce
    rotate([0, 0, i[2]])      // natočit podle natočení součástky na desce
      connectorNS25_WNp(3); // umístit konektor

A celé to tedy bude:

box_w=68.6;
box_d=53.3;
box_h=20;
difference()
{
    cube([box_w, box_d, box_h]);
    for(i=connectors)
        translate([i[0], i[1], 0])
            rotate([0, 0, i[2]]) 
                connectorNS25_WNp(3);
}

Kostka s vyříznutými konektory

protože difference udělá to, že vezme první věc uvnitř následujícího bloku a „vyřízne“ z ní všechno ostatní, co v tom bloku je, v tomto případě tedy vše, co vznikne vyhodnocením cyklu.

4. Vylepšení

To by v podstatě stačilo, ale ve sprše mě napadlo několik dalších úprav:
1. Nepotřebuji, aby konektory byly do desky „utopené“ celé (stačí o kousek víc, než základna konektoru, aby tam seděly, ale piny a zámek klidně můžou dole přesahovat. Tím ušetřím dobu tisku a taky trochu filamentu).
2. Konektor nemusí mít díry pro jednotlivé piny, můžou být všechny dohromady, důležitý je zámek na správné straně, aby tam konektor nešel dát obráceně.
3. Mohly by se hodit kolíky, na které by se shield nasadil (když budou kolíky vyšší, než piny konektorů, tak desku dám na kolíky a pak to na konektory sedne přesně samo).

Úprava 1 je jednoduchá – výšku přípravku nastavím řekněme o 3mm vyšší, než je základna konektoru, tj. box_h=3.3+3;
Úprava 2 znamenala přepracování (zjednodušení) modelu konektoru takto: základna a zámek zůstanou stejné, jednotlivé piny nahradím jednim kvádrem dohromady:

translate([-pins/2*2.54,-(base_d/2+pin_d_displacement),0]) 
{
  // base
  cube([base_w, base_d, base_h]);
  
  // lock
  translate([1.27, 0, base_h])
    cube([lock_w, lock_d, lock_h]); 
  
  // pin box
  translate([1.27-pin_w/2,lock_d,-3.3])
      cube([2.54*(pins-1)+pin_w,(base_d/2+pin_d_displacement)-lock_d+pin_w/2,pin_h]);
}

Po těchto dvou úpravách přípravek vypadá takto:

Zjednodušený přípravek


(rotace o 180 podle osy X je tam jednak aby se mi na to líp koukalo (ale to bych si mohl i jen otočit pohled), ale hlavně abych pak při přípravě 3D tisku nemusel objekt obracet vzhůru nohama).

Na úpravu 3, tj. přidělání pinů pro Arduino Uno, jsem si nejdřív zjistil originální umístění děr na této desce (odkaz jsem našel tady: https://blog.adafruit.com/2011/02/28/arduino-hole-dimensions-drawing/)
Pak mě napadlo, že jistě nejsem první, kdo to modeluje v OpenSCADu, našel jsem knihovnu https://github.com/kellyegan/OpenSCAD-Arduino-Mounting-Library a v ní jsem našel funkci holePlacement, která se mi právě hodila, protože ta vezme objekt, který za ní následuje, a umístí ho do místa každého montážního otvoru. Tím objektem bude v mém případě malý trn15, na který se deska nasadí.

Pro správné využití je potřeba pouze drobná transformace, protože v té knihovně mají desku posazenou oproti běžnému kreslení pootočeně, X mají kratší stranu a Y delší16, takže pro moje účely to je potřeba správně přetočit. Potřebujeme tedy otočit o 90° po směru hodinových ručiček, což je v matematice a mechanice obvykle -90°17 a protože se otáčí kolem středu souřadného systému, tak je po otočení ještě potřeba posunout do počátku (a to jsou ty dvě transformace před holePlacement):

Příparvek s čudlíkama

Další možnosti

Do tohoto tuturiálu se to už nevejde, ale je dobré zvážit ještě následující možnosti úprav:
– Udělat všechny otvory o něco větší, jednak kvůli obvyklým nepřesnostem 3D tisku děr, a teké i kvůli snazší manipulaci (když bude v přípravku napevno jeden konektor, tak to ještě vyndat půjde, ale když by jich tam pevně bylo dvacet, už to půjde velmi těžce)
– Doplnit do přípravku otvory podle dalších součástek, aby bylo možné je případně připájet dřív, než konektory, anebo v případě potřeby opravy desky položit už celou osazenou desku do přípravku
– Doplnit nožičky; protože konektory jsou skrz přípravek a vyčnívají dále dolů, při položení přípravku bu se vysunuly. Měl by mít nožišky alespoň tak dlouhé, jako vyčuhující část konektoru. Nožičky ale není potřeba tisknout (protože by se musely tisknout na druhé straně a to by nebylo snadné realizovat, je možné je udělat jinak, např. připravit si otvor pro šroubky, které poslouží jako ty nožičky.
– Doplnit úchyty, aby plně osazenou desku bylo snadné z přípravku vyjmout.
– Díry pro konektory udělat o něco mělčí, než by odpovídalo přesně velikosti konektoru. Po položení desky se tak snáze konektor přitiskne bez mezery k desce, zatímco když bude jeho hrana přesně zarovnaná s přípravkem, bude nutné při pájení i jen mírně prohnutou desku do přípravku přitláčet, aby po zapájení mezi konektorem a deskou nebyla mezera.

Všechny tyto náměty jsem nakonec zapracoval do návrhu a výsledek můžete vidět na fotografiíích úplně nahoře na začátku článku, ale abyste nemuseli scrollovat daleko, tady jsou:

Ještě tři poznámky na závěr:
1. Obrázky v tomto článku jsem postupně získal jako screenshot okna OpenSCADu (ve W10 Alt+PrintScreen sejme do clipboardu aktivní okno, to jsem pak vložil a uložil pomocí mého oblíbeného Irfan View, ale i Paint by asi stačil).
2. Aby byly všechny screenshoty hezky stejně velké, využil jsem volně dostupný prográmek „Sizer„, který umožňuje nastavit libovolné aplikační okno ve Windows na zvolenou velikost, aniž byste se museli pokoušet myší trefit na pixel. Skvělá věcička a rád jí tímto dělám reklamu.
3. Kdo jste se dobral až sem, gratuluji. Jestli se chcete podívat na úplně finální verzi, podle které jsem přípravek tiskl, tak tady je.


Poznámky:

  1. Konektory Ninigi NS25-w3p jsou ke koupi třeba v TME nebo obdobný u GES jako PSS 254/03G nebo v GME jako KK254.
  2. I tak se občas někomu povede zámkový konektor osadit obráceně a s katastrofálními následky – viz pád rakety Proton, kde někdo hrubou silou namontoval senzory vzhůru nohama. Bohužel ani zámkové konektory neřeší problém záměny dvou kabelů, viz Human error blamed for Vega launch failure – „Analysis of the telemetry from the mission, along with data from the production of the vehicle, led them to conclude that cables to two thrust vector control actuators were inverted. Commands intended to go to one actuator went instead to the other, triggering the loss of control.
  3. Často jsou vidět ručně osazené konektory mírně pootočené, kromě toho, že to špatně vypadá, může být i obtížné ke konektoru něco připojit.
  4. Je to jakoby žebrované – tušíte někdo, proč? Šetření materiálem? Nebo kvůli oplachu desky? Je nějaký praktický důvod?
  5. Takhle se v OpenSCADu říká tomu, co je v jiných prostředcích procedura, podprogram, dílek, součástka atd.
  6. Podle datasheetu je celková výška plastu 11,5 a z toho je základna 3,3
  7. Hloubka není v datasheetu není uvedena, změřil jsem ji proto přes nejtlustší místo
  8. Nazval jsem si to pin_d_displacement a tuto vzdálenost jsem prostě změřil na konektoru
  9. Akorát si to pak neuložte do toho původního souboru ;-)
  10. Musí to být z editoru desek, protože partlist vyexportovaný z editoru schematu souřadnice umístění na desce pochopitelně nemá. To jsem nevěděl, resp. podíval jsem se na ten „špatný“ export a nebyly tam, tak jsem hledal způsob jiný
  11. Tak trochu ve stylu „když jseš kladivo, všechno ostatní na světě je hřebík“
  12. \d znamená „libovolná číslice“, takže JP1 ze seznamu elementů výše tam nebude, protože P není cifra.
  13. Podstatně dýl jsem psal dokumentaci :-)
  14. Přesný tvar obvodu nepotřebuji.
  15. Trn bude váleček se zkosením nahoře pro snazší nasazování (spojení dvou válečků, jeden rovný, druhý zkosený a posazený na ten první).
  16. Obvykle se deska maluje naplocho, tj. X delší, Y kratší, tak to ostatně je i ve výše zmíněném nákresu rozměrů.
  17. V pravotočivých souřadných systémech je kladný směr otáčení smerem od osy X k ose Y, tedy proti směru hodinových ručiček.