5. týden: Výroba elektroniky Week 5: Electronics Production

Během pátého týdne bylo úkolem vytvořit elektronický obvod, který bude provádět nějakou akci (alespoň blikat). Podmínkou bylo, že se pro propojení součástek nesmí použít nepájivé kontaktní pole. During the fifth week, the task was to create an electronic circuit that performs some action (at least blinking). The condition was that a solderless breadboard must not be used to connect the components.

Dálkové ovládání hexapoda Hexapod remote control

Tento týden jsem se rozhodl sestrojit dálkové ovládání k mému závěrečnému projektu - hexapodovi. Cílem bylo navrhnout kontroler, který mi poskytne kontrolu nad všemi pohyby robota. Ovladač by měl umožňovat následující: This week I decided to build a remote control for my final project - the hexapod. The goal was to design a controller that gives me control over all the robot's movements. The controller should allow the following:

Mozkem ovladače bude Arduino Mega 2560 PRO. Ke komunikaci s Raspberry Pi 5, které se nachází v hexapodovi, použiji Bluetooth modul. Nastavené hodnoty se budou zobrazovat na OLED displeji. Zařízení je napájeno třemi AA bateriemi, jejichž napětí zvyšuji na 5 V pomocí step-up modulu. Celý tento projekt jsem se rozhodl integrovat na vlastní DPS (desku plošných spojů). The brain of the controller will be an Arduino Mega 2560 PRO. To communicate with the Raspberry Pi 5 located in the hexapod, I will use a Bluetooth module. The set values will be displayed on an OLED display. The device is powered by three AA batteries, whose voltage I step up to 5 V using a step-up module. I decided to integrate this entire project onto a custom PCB (printed circuit board).

Návrh DPS v programu KiCAD PCB design in KiCAD

Desku jsem navrhoval v bezplatném programu KiCAD. Prvním krokem byla tvorba schématu, kde se definují vývody použitých součástek a jejich propojení. Mnohé součástky má KiCAD v základu (tlačítka, rezistory, potenciometry), pro jiné je nutné schéma vytvořit nebo stáhnout. Schéma Arduina jsem stáhl z tohoto GitHub repozitáře. I designed the board in the free KiCAD program. The first step was to create a schematic, where the pins of the used components and their connections are defined. KiCAD has many components by default (buttons, resistors, potentiometers), for others it is necessary to create or download the schematic. I downloaded the Arduino schematic from this GitHub repository.

Pro zjednodušení jsem schémata složitějších modulů (joystick, Bluetooth, měnič napětí) nahradil standardními kolíkovými lištami (např. Conn_01x05_Socket pro joystick). Spoje k Arduinu jsem volil tak, aby byly vývody fyzicky blízko u sebe, což mi později velmi usnadnilo trasování desky. Jelikož logika Bluetooth modulu funguje na 3,3 V, bylo navíc nutné napětí z Arduina snížit pomocí napěťového děliče. For simplicity, I replaced the schematics of more complex modules (joystick, Bluetooth, voltage converter) with standard pin headers (e.g., Conn_01x05_Socket for the joystick). I chose the connections to the Arduino so that the pins were physically close to each other, which made routing the board much easier later. Since the logic of the Bluetooth module operates at 3.3 V, it was also necessary to reduce the voltage from the Arduino using a voltage divider.

Schéma projektu v KiCAD

Druhým krokem byl samotný návrh fyzické desky (v Editoru DPS). Zde je nutné každému symbolu přiřadit pouzdro (footprint), které definuje rozměry součástky, rozteče vývodů a montážní otvory, a následně mezi jednotlivými piny nakreslit vodivé spoje. Pouzdro joysticku jsem tvořil manuálně podle technického nákresu. Pouzdro Arduina se nacházelo ve stejném GitHub repozitáři jako jeho schéma a pouzdra kolíkových lišt, tlačítek, potenciometrů a rezistorů již KiCAD obsahuje. The second step was the actual design of the physical board (in the PCB Editor). Here it is necessary to assign a footprint to each symbol, which defines the dimensions of the component, pin spacing, and mounting holes, and then draw conductive traces between the individual pins. I created the joystick footprint manually according to the technical drawing. The Arduino footprint was located in the same GitHub repository as its schematic, and the footprints for pin headers, buttons, potentiometers, and resistors are already included in KiCAD.

Rozměry Joysticku ze stránky Drátek.cz

Zvolil jsem šířku spojů 0,8 mm a izolační mezeru 0,5 mm. Protože jsem vyráběl pouze jednovrstvou DPS (kde se cesty nesmí křížit), byl proces poměrně složitý. Abych si ušetřil trasování zemnících spojů, využil jsem funkci rozlité mědi (rozlitá zem). Zbytkové "ostrovy" země, které se s hlavní plochou nespojily, jsem vyřešil pomocí jumperů (propojení drátkem), které jsem připájel z vrchní strany desky. Jelikož měď rychle odvádí teplo, použil jsem pro usnadnění pájení spojů připojených k zemi termální odlehčení s krčky o šířce 0,65 mm s mezerou 0,65 mm. I chose a trace width of 0.8 mm and an isolation gap of 0.5 mm. Since I was only making a single-layer PCB (where traces cannot cross), the process was quite complex. To save myself from routing ground traces, I used the copper pour (ground pour) feature. I resolved the residual "islands" of ground that did not connect to the main plane using jumpers (wire connections), which I soldered from the top side of the board. Since copper conducts heat away quickly, I used thermal reliefs with 0.65 mm spoke width and 0.65 mm gap to make soldering the ground-connected joints easier.

Spodní frézovaná vrstva DPS Horní nefrézovaná vrstva DPS

Výroba DPS na CNC frézce PCB manufacturing on a CNC milling machine

Z KiCADu jsem vyexportoval výrobní data (.gbr pro cesty a ořez, .drl pro vrty). Příprava frézování (rychlost, hloubka...) a nastavení nástrojů probíhaly v softwaru MakeraCAM. Protože se frézuje spodní strana desky, musela být data zrcadlově převrácena. Za obrovskou pomoc a předání zkušeností v této fázi projektu bych rád poděkoval panu Ing. Krištofu Pučejdlovi. I exported the manufacturing data from KiCAD (.gbr for traces and edge cuts, .drl for drills). The milling preparation (speed, depth...) and tool setup took place in the MakeraCAM software. Because the bottom side of the board is milled, the data had to be mirrored. For the enormous help and sharing of experience in this phase of the project, I would like to thank Ing. Krištof Pučejdl.

Fotka z MakeraCAM

K výrobě posloužila školní CNC frézka Carvera Air. Desku kuprextitu (15 × 10 cm) jsme k podložce zafixovali oboustrannou lepicí páskou. The school's Carvera Air CNC milling machine was used for production. We fixed a copper-clad laminate board (15 × 10 cm) to the bed using double-sided adhesive tape.

Oboustranná lepicí páska na podkladu Stroj Makera Carvera Air s přilepenou kuprextitovou destičkou

Výroba probíhala ve čtyřech krocích: vyvrtání malých otvorů a předvrtání těch větších, vyfrézování měděných spojů, rozšíření otvorů větším vrtákem a na závěr vyříznutí vnějšího obrysu desky. The production took place in four steps: drilling small holes and pre-drilling larger ones, milling the copper traces, expanding the holes with a larger drill bit, and finally cutting out the outer contour of the board.

Cuprextit ve frézce s vyvrtanými otvory Cuprextit ve frézce s vyfrézovanými spoji Hotová DPS

Osazování součástkami a pájení Component assembly and soldering

Seznam použitých součástek: List of used components:

Fotka použitých součástek

Pro pájení jsem použil 16 let starou sadu ROTHENBERGER od dědy. Nástroj s velkým hrotem a hrubou pájkou (1,5 mm) nebyl na drobnou elektroniku vůbec vhodný. Největší a téměř fatální chybou však bylo použití tavidla z této sady. Bylo to totiž instalatérské tavidlo, které je elektricky vodivé. For soldering, I used a 16-year-old ROTHENBERGER set from my grandfather. A tool with a large tip and thick solder (1.5 mm) was not suitable for tiny electronics at all. However, the biggest and almost fatal mistake was using the flux from this set. It was plumbing flux, which is electrically conductive.

Pájecí sada

Součástky (tlačítka, rezistory, potenciometry) jsem pájel přímo do desky. Moduly a displej se zasouvají do předem připájených dutinkových lišt, takže je lze kdykoliv vyjmout. Joysticky jsou drženy nad deskou pomocí 4 mm vysokých spacerů tištěných na 3D tiskárně, které se následně prošroubují M2 × 8mm šroubky a na druhé straně desky upevní maticí. Stejným způsobem je displej držen ve výšce 16 mm pomocí šroubků M2 × 20mm. Pro upevnění držáku baterek jsem v DPS navrhl dva otvory pro přišroubování, nakonec jsem ale použil tavné lepidlo. I soldered the components (buttons, resistors, potentiometers) directly to the board. The modules and display are plugged into pre-soldered female headers, so they can be removed at any time. The joysticks are held above the board by 4 mm high spacers printed on a 3D printer, which are then screwed through with M2 × 8mm screws and secured with a nut on the other side of the board. In the same way, the display is held at a height of 16 mm using M2 × 20mm screws. To attach the battery holder, I designed two screw holes in the PCB, but in the end I used hot melt adhesive.

Hromádka zkrácených lišt Arduino bez napájených pinů Arduino s napájenými piny Hotové DPS zeshora Hotové DPS zespodu Hotové DPS zezadu

Během manipulace s deskou před přišroubováním joysticků se mi bohužel podařilo jeden joystick odtrhnout i s měděnými cestami. Spoje jsem musel nahradit drátky. Unfortunately, while handling the board before screwing on the joysticks, I managed to rip off one joystick along with the copper traces. I had to replace the connections with wires.

Utržené měděné cestičky Opravené DPS

Problémy s tavidlem Flux problems

Po prvním zapojení se Arduino chovalo naprosto nevyzpytatelně. Napětí na analogových vstupech kolísalo mezi 1 až 3 volty, když mělo být 5. Postupně zhasínaly různé moduly, až přestaly svítit i indikační LED přímo na Arduinu. Po hodinách zoufalého debugování jsem zjistil příčinu: vodivé zbytky tavidla tvořily zkraty a parazitní napěťové děliče. After the first power-up, the Arduino behaved completely erratically. The voltage on the analog inputs fluctuated between 1 and 3 volts when it should have been 5. Various modules gradually turned off, until even the indicator LEDs directly on the Arduino stopped shining. After hours of desperate debugging, I found the cause: conductive flux residues were forming short circuits and parasitic voltage dividers.

Následoval drastický pokus o záchranu projektu. Celou desku i s připájenými součástkami jsem polil 99% isopropylalkoholem a vydrhnul kartáčkem. Arduino si navíc prošlo půlhodinovou koupelí v horké vodě s Jarem. Po důkladném vysušení fénem obvod zázračně ožil a plně funguje (až na tlačítko v pravém joysticku, kde se při čištění utrhl opravný drátek). A drastic attempt to save the project followed. I poured 99% isopropyl alcohol over the entire board with the soldered components and scrubbed it with a brush. Furthermore, the Arduino went through a half-hour bath in hot water with dish soap. After thorough drying with a hair dryer, the circuit miraculously came back to life and works fully (except for the button in the right joystick, where a repair wire broke off during cleaning).

CAD návrh CAD design

Krabičku jsem modeloval ve Fusion 360 s ohledem na příjemné držení v rukou a co nejmenší rozměry. DPS má v rozích otvory o průměru 2 mm, díky čemuž ji lze v krabičce uchytit pomocí čtyř M2 × 6 mm šroubků. Zespodu krabičky je otvor o rozměrech 20 × 12,5 mm, do kterého je zatlačen kolébkový spínač. Víko bylo nutné ladit na několik pokusů, aby všechny otvory perfektně lícovaly s ovládacími prvky. Abych viděl na LED měniče napětí a Bluetooth modulu, udělal jsem na obou stranách krytu otvory. Prázdné místo na krytu jsem vyplnil logem ČVUT, které jsem pomocí funkce Canvas vložil do roviny krytu a obkreslil pomocí Fit Point Spline. Víko je ke krabičce připevněno pomocí čtyř M2 × 8 mm šroubků. I modeled the case in Fusion 360 with consideration for a comfortable grip and the smallest possible dimensions. The PCB has holes with a diameter of 2 mm in the corners, which allows it to be mounted in the case using four M2 × 6 mm screws. On the bottom of the case is a 20 × 12.5 mm hole, into which the rocker switch is pressed. The lid had to be tuned over several attempts so that all holes perfectly aligned with the controls. To be able to see the LEDs of the voltage converter and the Bluetooth module, I made holes on both sides of the cover. I filled the empty space on the cover with the CTU logo, which I inserted into the cover plane using the Canvas function and traced using a Fit Point Spline. The lid is attached to the case using four M2 × 8 mm screws.

Sketch krabičky ve Fusion 360 Model krabičky ve Fusion 360 Sketch krytu ovládání ve Fusion 360 Tvorba loga ČVUT na krytu Model krytu ovládání ve Fusion 360

Jelikož se tlačítka a potenciometry nacházejí pod úrovní víka, bylo nutné vymodelovat nástavce. Knoflíky pro tlačítka jsem stáhl z GrabCAD a následně jsem je ve Fusion 360 prodloužil na 16 mm. Nástavec na potenciometry jsem tvořil sám. Do potenciometru zapadne díky kruhovému otvoru o průměru 6,1 mm, ve kterém je příčka o tloušťce 0,9 mm. Since the buttons and potentiometers are located below the lid level, it was necessary to model extensions. I downloaded the button caps from GrabCAD and then lengthened them to 16 mm in Fusion 360. I created the potentiometer extension myself. It fits onto the potentiometer thanks to a circular hole with a diameter of 6.1 mm, which contains a 0.9 mm thick crossbar.

Model nasazovacího knoflíku na tlačítko Model Nástavce na potenciometr

3D tisk 3D printing

Hotové modely jsem vyexportoval z Fusionu (Utilities -> 3D print) do formátu 3MF a naslicoval v programu Bambu Studio. Jako materiál jsem vybral PLA a tiskl jsem na tiskárně Bambu Lab A1 Mini s 0,4 mm tryskou při následujícím nastavení: I exported the finished models from Fusion (Utilities -> 3D print) into the 3MF format and sliced them in the Bambu Studio program. I chose PLA as the material and printed on the Bambu Lab A1 Mini printer with a 0.4 mm nozzle using the following settings:

Zbylá nastavení jsem ponechal na výchozích hodnotách vybraného tiskového profilu. I left the remaining settings at the default values of the selected print profile.

Pro otvor kolébkového spínače bylo potřeba vygenerovat podpěry. Zvolil jsem následující nastavení podpěr: Supports needed to be generated for the rocker switch hole. I chose the following support settings:

Ostatní nastavení podpěr zůstalo výchozí. Other support settings remained default.

Model krytu v Bambu Studiu Model krabicky v Bambu Studiu Modely knoflíků a násady na potenciometry v Bambu Studiu Vytištěná krabička Vytištěný kryt Elektronika zasazená do krabičky

Programování (Arduino IDE) Programming (Arduino IDE)

Kód se stará o vizualizaci vstupů na OLED displeji, k čemuž používá knihovnu U8g2. Pohyb joysticků je znázorněn kruhy, které se při stisku vyplní. Stav tlačítek je v horní části a potenciometry jsou zobrazeny jako čtyři sloupcové grafy uprostřed. The code takes care of visualizing the inputs on the OLED display, for which it uses the U8g2 library. The movement of the joysticks is represented by circles that fill up when pressed. The state of the buttons is at the top, and the potentiometers are displayed as four bar graphs in the middle.

C++ controler.cpp
#include <Arduino.h>
#include <U8g2lib.h> // knihovna pro oled
#include <Wire.h>    // sbernice i2c

// objekt displeje
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

// piny tlacitek
const int pinSW1 = 27;
const int pinSW2 = 5;
const int pinSW3 = 3;

// piny potenciometru
const int pinRV1 = A0;
const int pinRV2 = A1;
const int pinRV3 = A14;
const int pinRV4 = A12;

// levy joystick
const int joy1X = A10;
const int joy1Y = A8;
const int joy1Btn = A6;

// pravy joystick
const int joy2X = A7;
const int joy2Y = A5;
const int joy2Btn = A3;

void setup() {
    delay(50); // kratka pauza

    // pullup odpory pro tlacitka
    pinMode(pinSW1, INPUT_PULLUP);
    pinMode(pinSW2, INPUT_PULLUP);
    pinMode(pinSW3, INPUT_PULLUP);
    pinMode(joy1Btn, INPUT_PULLUP);
    pinMode(joy2Btn, INPUT_PULLUP);

    u8g2.setBusClock(400000); // rychle i2c
    u8g2.begin();             // start displeje
}

void loop() {
    // cteni potenciometru
    unsigned int valRV1 = analogRead(pinRV1);
    unsigned int valRV2 = analogRead(pinRV2);        // normalni smer
    unsigned int valRV3 = 1023 - analogRead(pinRV3); // obracena hodnota
    unsigned int valRV4 = analogRead(pinRV4);

    // cteni stisku tlacitek
    bool btn1 = !digitalRead(pinSW1);
    bool btn2 = !digitalRead(pinSW2);
    bool btn3 = !digitalRead(pinSW3);
    bool j1Btn = !digitalRead(joy1Btn);
    bool j2Btn = !digitalRead(joy2Btn);

    // osy joy 1 inverzni
    long dX1 = 512 - analogRead(joy1X); 
    long dY1 = 512 - analogRead(joy1Y);
    
    long distSq1 = dX1 * dX1 + dY1 * dY1; // ctverec vzdalenosti
    
    if (distSq1 > 262144L) { // orez do kruhu
    long dist1 = sqrt(distSq1);
    dX1 = (dX1 * 512) / dist1;
    dY1 = (dY1 * 512) / dist1;
    }
    
    // pozice joy 1 v pixelech
    int drawJ1X = 20 + (dX1 / 32); 
    int drawJ1Y = 32 + (dY1 / 32);

    // osy joy 2 normalni
    long dX2 = analogRead(joy2X) - 512;
    long dY2 = analogRead(joy2Y) - 512;
    
    long distSq2 = dX2 * dX2 + dY2 * dY2; // ctverec vzdalenosti
    
    if (distSq2 > 262144L) { // orez do kruhu
    long dist2 = sqrt(distSq2);
    dX2 = (dX2 * 512) / dist2;
    dY2 = (dY2 * 512) / dist2;
    }
    
    // pozice joy 2 v pixelech
    int drawJ2X = 106 + (dX2 / 32); 
    int drawJ2Y = 32 + (dY2 / 32);

    u8g2.clearBuffer(); // vymaz pameti displeje

    // obrysy obou joysticku
    u8g2.drawCircle(20, 32, 20);   
    u8g2.drawCircle(106, 32, 20);  
    
    // tecka leveho joysticku plna pri stisku
    if (j1Btn) u8g2.drawDisc(drawJ1X, drawJ1Y, 4);
    else u8g2.drawCircle(drawJ1X, drawJ1Y, 4);

    // tecka praveho joysticku plna pri stisku
    if (j2Btn) u8g2.drawDisc(drawJ2X, drawJ2Y, 4);
    else u8g2.drawCircle(drawJ2X, drawJ2Y, 4);

    // ramecky pro grafy
    u8g2.drawFrame(46, 27, 6, 36);   
    u8g2.drawFrame(56, 27, 6, 36);
    u8g2.drawFrame(66, 27, 6, 36);
    u8g2.drawFrame(76, 27, 6, 36);

    // prevod hodnot na pixely
    int h1 = (valRV1 * 36) >> 10;
    int h2 = (valRV2 * 36) >> 10;
    int h3 = (valRV3 * 36) >> 10;
    int h4 = (valRV4 * 36) >> 10;

    // sloupce grafu zleva doprava
    u8g2.drawBox(46, 63 - h4, 6, h4); // sloupec rv4
    u8g2.drawBox(56, 63 - h3, 6, h3); // sloupec rv3
    u8g2.drawBox(66, 63 - h1, 6, h1); // sloupec rv1
    u8g2.drawBox(76, 63 - h2, 6, h2); // sloupec rv2

    // vykresleni hornich tlacitek
    if (btn1) u8g2.drawDisc(51, 8, 4); else u8g2.drawCircle(51, 8, 4);
    if (btn2) u8g2.drawDisc(64, 8, 4); else u8g2.drawCircle(64, 8, 4);
    if (btn3) u8g2.drawDisc(77, 8, 4); else u8g2.drawCircle(77, 8, 4);

    u8g2.sendBuffer(); // zapis na displej
}

A nakonec fotka hotového dálkového ovládání pro hexapoda: And finally, a photo of the finished hexapod remote control:

Hotový model dálkového ovládání