Tartalomjegyzék:
Videó: Robot gyöngyök rendezése: 3 lépés (képekkel)
2024 Szerző: John Day | [email protected]. Utoljára módosítva: 2024-01-30 09:42
Ebben a projektben robotot fogunk építeni a Perler gyöngyök szín szerinti válogatásához.
Mindig szerettem volna színválogató robotot építeni, így amikor a lányom érdeklődni kezdett a Perler gyöngyök készítése iránt, ezt tökéletes lehetőségnek láttam.
A Perler -gyöngyöket olvadt művészeti projektek készítésére használják, sok gyöngyöt egy rácsra helyezve, majd vasalóval összeolvasztva. Általában ezeket a gyöngyöket óriási, 22 000 gyöngyös vegyes színű csomagban vásárolja meg, és sok időt tölt a kívánt szín keresésével, ezért azt gondoltam, hogy a válogatás növeli a művészet hatékonyságát.
A Phidgets Inc. -nél dolgozom, ezért többnyire Phidgets -t használtam ehhez a projekthez - de ezt bármilyen megfelelő hardverrel meg lehet tenni.
1. lépés: Hardver
Íme, amit én szoktam építeni. 100% -ban a phidgets.com alkatrészeiből építettem, és a ház körül fekvő dolgokból.
Phidgets táblák, motorok, hardverek
- HUB0000 - VINT Hub Phidget
- 1108 - Mágneses érzékelő
- 2x STC1001 - 2,5A léptető Phidget
- 2x 3324 - 42STH38 NEMA -17 bipoláris sebességváltó
- 3x 3002 - Phidget kábel 60 cm
- 3403 - USB2.0 4 portos hub
- 3031 - Női copf 5,5x2,1 mm
- 3029 - 2 vezetékes 100 'csavart kábel
- 3604 - 10 mm -es fehér LED (10 db -os táska)
- 3402 - USB webkamera
Más részek
- 24VDC 2.0A tápegység
- Fa- és fémhulladék a garázsból
- Zip kötések
- Műanyag edény, levágva az alját
2. lépés: Tervezze meg a robotot
Valamit meg kell terveznünk, amely egyetlen gyöngyöt vehet ki a bemeneti garatból, a webkamera alá kell helyezni, majd áthelyezni a megfelelő kukába.
Gyöngyszedés
Úgy döntöttem, hogy az 1. részt 2 darab kerek rétegelt lemezből készítem, mindegyiken lyukat fúrva ugyanott. Az alsó darab rögzítve van, a felső pedig egy léptetőmotorhoz van rögzítve, amely el tudja forgatni a gyöngyökkel töltött garat alatt. Amikor a lyuk a garat alatt halad, egyetlen gyöngyöt vesz fel. Ezt követően forgathatom a webkamera alatt, majd tovább forgathatom, amíg össze nem egyezik az alsó rész lyukával, és ekkor átesik.
Ezen a képen azt tesztelem, hogy a rendszer működik -e. Minden rögzítve van, kivéve a felső kerek rétegelt lemezdarabot, amely alatta egy látómezőhöz van rögzítve. A webkamera még nincs felszerelve. Most csak a Phidget vezérlőpultot használom, hogy motorhoz forduljak.
Gyöngyök tárolása
A következő rész az egyes színek tárolására szolgáló tárolórendszer kialakítása. Úgy döntöttem, hogy egy második léptetőmotort használok egy kerek tartály alátámasztására és elforgatására, egyenletesen elhelyezett rekeszekkel. Ezzel elforgatható a megfelelő rekesz a lyuk alatt, amelyből a gyöngy kiesik.
Ezt kartonból és ragasztószalagból építettem. A legfontosabb itt a következetesség - minden rekesznek azonos méretűnek kell lennie, és az egészet egyenletesen kell súlyozni, így ugrás nélkül forog.
A gyöngyök eltávolítása egy szorosan illeszkedő fedél segítségével történik, amely egyszerre egyetlen rekeszt tár fel, így a gyöngyök kiönthetők.
Kamera
A webkamera a felső lemez fölé van szerelve a garat és az alsó lemezlyuk helye között. Ez lehetővé teszi a rendszer számára, hogy megnézze a gyöngyöt, mielőtt leejti. A fényképezőgép alatti gyöngyök megvilágítására LED -et használnak, a környezeti fény pedig blokkolva van a következetes megvilágítási környezet biztosítása érdekében. Ez nagyon fontos a pontos színérzékeléshez, mivel a környezeti megvilágítás valóban kivetheti az érzékelt színeket.
Helyérzékelés
Fontos, hogy a rendszer képes legyen érzékelni a gyöngyleválasztó forgását. Ez a beállítás a kezdeti pozíció beállítására szolgál indításkor, de annak észlelésére is, hogy a léptetőmotor ki lett -e szinkronizálva. Az én rendszeremben egy gyöngy néha elakad, miközben felveszi, és a rendszernek képesnek kell lennie észlelni és kezelni ezt a helyzetet - egy kicsit mentve és megpróbálva.
Ennek kezelésére sokféle módszer létezik. Úgy döntöttem, hogy 1108 -as mágneses érzékelőt használok, mágnessel a felső lemez szélébe ágyazva. Ez lehetővé teszi, hogy minden fordulaton ellenőrizhessem a pozíciót. A jobb megoldás valószínűleg a léptetőmotor kódolója lenne, de egy 1108 -as feküdt, ezért ezt használtam.
Fejezd be a robotot
Ezen a ponton mindent kidolgoztak és teszteltek. Itt az ideje, hogy mindent szépen telepítsen, és áttérjen az írószoftverre.
A 2 léptetőmotort STC1001 léptetővezérlők hajtják. A HUB000 - USB VINT hub a léptetővezérlők futtatására, valamint a mágneses érzékelő leolvasására és a LED meghajtására szolgál. A webkamera és a HUB0000 egyaránt egy kis USB -elosztóhoz van csatlakoztatva. A motorok táplálásához 3031 -es copfot és néhány vezetéket használnak 24V -os tápegységgel együtt.
Lépés: Írja be a kódot
Ehhez a projekthez a C# és a Visual Studio 2015 szolgál. Töltse le a forrást az oldal tetején, és kövesse - a fő szakaszokat az alábbiakban ismertetjük
Inicializálás
Először létre kell hoznunk, meg kell nyitnunk és inicializálnunk kell a Phidget objektumokat. Ez az űrlap betöltése eseményben történik, és a Phidget csatolók kezelői.
private void Form1_Load (objektumküldő, EventArgs e) {
/ * Inicializálja és nyissa meg a Phidgeteket */
top. HubPort = 0; top. Attach += Top_Attach; top. Detach += Top_Detach; top. PositionChange += Top_PositionChange; fel. Nyissa ();
alsó. HubPort = 1;
bottom. Attach += Bottom_Attach; bottom. Detach += Bottom_Detach; bottom. PositionChange += Bottom_PositionChange; alul. Nyissa ();
magSensor. HubPort = 2;
magSensor. IsHubPortDevice = igaz; magSensor. Attach += MagSensor_Attach; magSensor. Detach += MagSensor_Detach; magSensor. SensorChange += MagSensor_SensorChange; magSensor. Open ();
led. HubPort = 5;
led. IsHubPortDevice = igaz; led. Channel = 0; led. Attach += Led_Attach; led. Detach += Led_Detach; led. Open (); }
private void Led_Attach (objektumküldő, Phidget22. Events. AttachEventArgs e) {
ledAttachedChk. Checked = igaz; led. State = igaz; ledChk. Checked = igaz; }
private void MagSensor_Attach (objektumküldő, Phidget22. Events. AttachEventArgs e) {
magSensorAttachedChk. Checked = igaz; magSensor. SensorType = VoltageRatioSensorType. PN_1108; magSensor. DataInterval = 16; }
private void Bottom_Attach (objektumküldő, Phidget22. Events. AttachEventArgs e) {
bottomAttachedChk. Checked = igaz; bottom. CurrentLimit = bottomCurrentLimit; alsó. Engaged = igaz; bottom. VelocityLimit = bottomVelocityLimit; bottom. Acceleration = bottomAccel; bottom. DataInterval = 100; }
private void Top_Attach (objektumküldő, Phidget22. Events. AttachEventArgs e) {
topAttachedChk. Checked = igaz; top. CurrentLimit = topCurrentLimit; top. Engaged = igaz; top. RescaleFactor = -1; top. VelocityLimit = -topVelocityLimit; fel. Gyorsulás = -topAccel; top. DataInterval = 100; }
Az inicializálás során beolvasunk minden elmentett színinformációt is, így folytatható az előző futtatás.
Motor pozicionálás
A motorkezelési kód a motorok mozgatásának kényelmi funkcióiból áll. Az általam használt motorok fordulatonként 3, 200 1/16 lépést jelentenek, ezért ehhez konstansot hoztam létre.
A felső motor esetében 3 pozíciót szeretnénk elküldeni a motornak: a webkamerát, a lyukat és a pozicionáló mágnest. Van egy funkció az egyes pozíciókba való utazáshoz:
private void nextMagnet (logikai várakozás = hamis) {
double posn = top. Position % stepsPerRev;
top. TargetPosition += (stepsPerRev - posn);
ha (várj)
while (top. IsMoving) Thread. Sleep (50); }
private void nextCamera (Boole -várakozás = hamis) {
double posn = top. Position % stepsPerRev; if (posn <Properties. Settings. Default.cameraOffset) top. TargetPosition += (Properties. Settings. Default.cameraOffset - posn); else top. TargetPosition + = ((Properties. Settings. Default.cameraOffset - posn) + stepsPerRev);
ha (várj)
while (top. IsMoving) Thread. Sleep (50); }
private void nextHole (Boole -várakozás = hamis) {
double posn = top. Position % stepsPerRev; if (posn <Properties. Settings. Default.holeOffset) top. TargetPosition += (Properties. Settings. Default.holeOffset - posn); else top. TargetPosition + = ((Properties. Settings. Default.holeOffset - posn) + stepsPerRev);
ha (várj)
while (top. IsMoving) Thread. Sleep (50); }
A futás megkezdése előtt a felső lemezt a mágneses érzékelő segítségével igazítják. Az alignMotor funkció bármikor meghívható a felső lemez igazításához. Ez a funkció először gyorsan felforgatja a lemezt 1 teljes fordulatra, amíg meg nem látja a mágneses adatokat egy küszöbérték felett. Ezután egy kicsit biztonsági mentést készít, és lassan halad előre, lassan rögzítve az érzékelő adatait. Végül beállítja a pozíciót a mágnesadatok maximális helyére, és visszaállítja a pozícióeltolást 0. Így a maximális mágnespozíciónak mindig a (felső. Pozíció % lépésekPerRev) értéken kell lennie.
Menet összehangolásaMotorThread; Boolean sawMagnet; dupla magSensorMax = 0; private void alignMotor () {
// Keresse meg a mágnest
top. DataInterval = top. MinDataInterval;
sawMagnet = hamis;
magSensor. SensorChange += magSensorStopMotor; top. VelocityLimit = -1000;
int tryCount = 0;
próbáld újra:
top. TargetPosition += stepsPerRev;
while (top. IsMoving &&! sawMagnet) Thread. Sleep (25);
ha (! sawMagnet) {
if (tryCount> 3) {Console. WriteLine ("Az igazítás nem sikerült"); top. Engaged = hamis; alsó. Engaged = hamis; runtest = hamis; Visszatérés; }
tryCount ++;
Console. WriteLine ("Elakadtunk? Próbálunk biztonsági másolatot készíteni …"); top. TargetPosition -= 600; while (top. IsMoving) Thread. Sleep (100);
újra megpróbálkozni;
}
top. VelocityLimit = -100;
magData = új lista> (); magSensor. SensorChange += magSensorCollectPositionData; top. TargetPosition += 300; while (top. IsMoving) Thread. Sleep (100);
magSensor. SensorChange -= magSensorCollectPositionData;
top. VelocityLimit = -topVelocityLimit;
KeyValuePair max = magData [0];
foreach (KeyValuePair pár a magDatában) if (pair. Value> max. Value) max = pair;
top. AddPositionOffset (-max. Key);
magSensorMax = max. Value;
top. TargetPosition = 0;
while (top. IsMoving) Thread. Sleep (100);
Console. WriteLine ("Az igazítás sikerült");
}
Lista> magData;
private void magSensorCollectPositionData (objektumküldő, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {magData. Add (új KeyValuePair (top. Position, e. SensorValue)); }
private void magSensorStopMotor (objektumküldő, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {
if (top. IsMoving && e. SensorValue> 5) {top. TargetPosition = top. Position - 300; magSensor. SensorChange -= magSensorStopMotor; sawMagnet = igaz; }}
Végül az alsó motort úgy irányítják, hogy elküldik a gyöngytartó egyik pozíciójába. Ehhez a projekthez 19 pozíciónk van. Az algoritmus a legrövidebb utat választja, és az óramutató járásával megegyező vagy az óramutató járásával ellentétes irányba fordul.
private int BottomPosition {get {int posn = (int) bottom. Position % stepsPerRev; if (posn <0) posn += stepsPerRev;
return (int) Math. Round ((((posn * beadCompartments) / (kettős) lépésekPerRev));
} }
private void SetBottomPosition (int posn, bool wait = false) {
posn = posn % beadCompartments; double targetPosn = (posn * stepsPerRev) / beadCompartments;
dupla áramPosn = alsó. Pozíció % lépésekPerRev;
dupla posnDiff = targetPosn - currentPosn;
// Tartsa teljes lépésekben
posnDiff = ((int) (posnDiff / 16)) * 16;
if (posnDiff <= 1600) bottom. TargetPosition += posnDiff; else bottom. TargetPosition - = (stepsPerRev - posnDiff);
ha (várj)
while (bottom. IsMoving) Thread. Sleep (50); }
Kamera
Az OpenCV a webkameráról származó képek olvasására szolgál. A kamera szála a fő rendezési szál elindítása előtt kezdődik. Ez a szál folyamatosan olvassa a képeket, kiszámítja az átlagos színt egy adott régióhoz az Mean segítségével, és frissíti a globális színváltozót. A szál a HoughCircles alkalmazásával egy gyöngyöt vagy a felső lemezen lévő lyukat is észleli, hogy finomítsa azt a területet, amelyet a színérzékelésre néz. A küszöbértéket és a HoughCircles számokat próba és hiba útján határozták meg, és nagymértékben függnek a webkamerától, a megvilágítástól és a távolságtól.
bool runVideo = igaz; bool videoRunning = false; VideoCapture rögzítés; Szál cvThread; Szín észlelveSzín; Logikai észlelés = hamis; int detectCnt = 0;
private void cvThreadFunction () {
videoRunning = hamis;
capture = új VideoCapture (kiválasztottKamera);
using (Ablak ablak = új ablak ("rögzítés")) {
Mat kép = új Mat (); Mat kép2 = új Mat (); while (runVideo) {capture. Read (kép); if (image. Empty ()) break;
ha (észlel)
detectCnt ++; else detectCnt = 0;
if (észlelés || circleDetectChecked || showDetectionImgChecked) {
Cv2. CvtColor (kép, kép2, ColorConversionCodes. BGR2GRAY); Mat thres = image2. Threshold ((dupla) Properties. Settings. Default.videoThresh, 255, ThresholdTypes. Binary); thres = thres. GaussianBlur (új OpenCvSharp. Size (9, 9), 10);
if (showDetectionImgChecked)
image = thres;
if (észleli || circleDetectChecked) {
CircleSegment gyöngy = thres. HoughCircles (HoughMethods. Gradient, 2, /*thres. Rows/4*/ 20, 200, 100, 20, 65); if (gyöngy.hossz> = 1) {image. Kör (gyöngy [0]. Center, 3, new Scalar (0, 100, 0), -1); image. Kör (gyöngy [0]. Központ, (int) gyöngy [0]. Sugár, új skalár (0, 0, 255), 3); if (gyöngy [0]. Rádius> = 55) {Properties. Settings. Default.x = (decimális) gyöngy [0]. Center. X + (decimális) (gyöngy [0]. Radius / 2); Tulajdonságok. Beállítások. Default.y = (tizedes) gyöngy [0]. Központ. Y - (tizedes) (gyöngy [0]. Rádius / 2); } else {Properties. Settings. Default.x = (decimális) gyöngy [0]. Center. X + (tizedes) (gyöngy [0]. Sugár); Properties. Settings. Default.y = (decimális) gyöngy [0]. Center. Y - (decimális) (gyöngy [0]. Sugár); } Properties. Settings. Default.size = 15; Properties. Settings. Default.height = 15; } más {
CircleSegment körök = thres. HoughCircles (HoughMethods. Gradient, 2, /*thres. Rows/4*/ 5, 200, 100, 60, 180);
if (körök.hossz> 1) {Lista xs = körök. Kiválasztás (c => c. Center. X). ToList (); xs. Sort (); Lista ys = körök. Válassza a (c => c. Center. Y). ToList (); ys. Sort ();
int mediánX = (int) xs [xs. Count / 2];
int mediánY = (int) ys [ys. Count / 2];
if (medianX> kép. Szélesség - 15)
medianX = kép. Szélesség - 15; if (medianY> image. Height - 15) medianY = image. Height - 15;
kép. Kör (mediánX, mediánY, 100, új skalár (0, 0, 150), 3);
ha (észlel) {
Properties. Settings. Default.x = medianX - 7; Properties. Settings. Default.y = mediánY - 7; Properties. Settings. Default.size = 15; Properties. Settings. Default.height = 15; }}}}}
Rect r = new Rect ((int) Properties. Settings. Default.x, (int) Properties. Settings. Default.y, (int) Properties. Settings. Default.size, (int) Properties. Settings. Default.height);
Mat beadSample = új Mat (kép, r);
Skalár avgColor = Cv2. Mean (gyöngyminta); detectColor = Color. FromArgb ((int) avgColor [2], (int) avgColor [1], (int) avgColor [0]);
kép. Téglalap (r, új skalár (0, 150, 0));
window. ShowImage (kép);
Cv2. WaitKey (1); videoRunning = igaz; }
videoRunning = hamis;
} }
private void cameraStartBtn_Click (objektumküldő, EventArgs e) {
if (cameraStartBtn. Text == "start") {
cvThread = új szál (új ThreadStart (cvThreadFunction)); runVideo = igaz; cvThread. Start (); cameraStartBtn. Text = "stop"; while (! videoRunning) Thread. Sleep (100);
updateColorTimer. Start ();
} más {
runVideo = hamis; cvThread. Join (); cameraStartBtn. Text = "start"; }}
Szín
Most már meg tudjuk határozni a gyöngy színét, és a szín alapján eldönthetjük, hogy melyik tartályba dobjuk.
Ez a lépés a színek összehasonlításán alapul. Szeretnénk megkülönböztetni a színeket, hogy korlátozzuk a hamis pozitív eredményeket, de elegendő küszöbértéket is lehetővé teszünk a hamis negatívok korlátozásához. A színek összehasonlítása valójában meglepően bonyolult, mivel az, ahogyan a számítógépek tárolják a színeket RGB -ként, és ahogyan az emberek érzékelik a színeket, nem korrelálnak lineárisan. Ami még rosszabb, a fény színét is figyelembe kell venni.
Vannak bonyolult algoritmusok a színkülönbség kiszámítására. A CIE2000 -et használjuk, amely 1 közeli számot ad ki, ha 2 szín nem lenne megkülönböztethető az ember számára. A bonyolult számítások elvégzéséhez a ColorMine C# könyvtárat használjuk. Az 5 -ös DeltaE érték jó kompromisszumot kínál a hamis pozitív és a hamis negatív között.
Mivel gyakran több szín van, mint a konténerek, az utolsó helyet foglalatos szemetesként tartják fenn. Ezeket általában félreteszem, hogy a gépen futhassanak második menetben.
Lista
színek = új lista (); lista színpanelek = új lista (); Lista színeiTxts = new List (); Lista colorCnts = új List ();
const int számColorSpots = 18;
const int ismeretlenColorIndex = 18; int findColorPosition (C szín) {
Console. WriteLine ("Szín keresése …");
var cRGB = új Rgb ();
cRGB. R = c. R; cRGB. G = c. G; cRGB. B = c. B;
int bestMatch = -1;
kettős mérkőzésDelta = 100;
for (int i = 0; i <colors. Count; i ++) {
var RGB = új Rgb ();
RGB. R = színek . R; RGB. G = színek . G; RGB. B = színek . B;
dupla delta = cRGB. Compare (RGB, új CieDe2000Comparison ());
// dupla delta = deltaE (c, színek ); Console. WriteLine ("DeltaE (" + i. ToString () + "):" + delta. ToString ()); if (delta <matchDelta) {matchDelta = delta; bestMatch = i; }}
if (matchDelta <5) {Console. WriteLine ("Talált! (Posn:" + bestMatch + "Delta:" + matchDelta + ")"); return bestMatch; }
if (colors. Count <numColorSpots) {Console. WriteLine ("Új szín!"); színek. Add (c); this. BeginInvoke (új művelet (setBackColor), új objektum {colors. Count - 1}); writeOutColors (); visszatérés (színek. Szám - 1); } else {Console. WriteLine ("Ismeretlen szín!"); return ismeretlenColorIndex; }}
Rendezési logika
A rendezési funkció összegyűjti az összes darabot a gyöngyök rendezéséhez. Ez a funkció egy dedikált szálban fut; mozgassa a felső lemezt, érzékelje a gyöngy színét, tegye a kukába, győződjön meg arról, hogy a felső lemez egy vonalban marad, számolja a gyöngyöket stb. A futás akkor is leáll, amikor megtelik a zsákgyűjtő tartály - Különben csak túlcsorduló gyöngyökkel végzünk.
Szál colourTestThread; Boolean runtest = false; void colourTest () {
ha (! top. Engaged)
top. Engaged = igaz;
ha (! alul. Engaged)
alsó. Engaged = igaz;
while (runtest) {
nextMagnet (igaz);
Menet. Alvás (100); try {if (magSensor. SensorValue <(magSensorMax - 4)) alignMotor (); } catch {alignMotor (); }
nextCamera (igaz);
észlelés = igaz;
while (detectCnt <5) Thread. Sleep (25); Console. WriteLine ("Detect Count:" + detectCnt); észlelés = hamis;
C szín = észlelt szín;
this. BeginInvoke (új művelet (setColorDet), új objektum {c}); int i = findColorPosition (c);
SetBottomPosition (i, igaz);
nextHole (igaz); colorCnts ++; this. BeginInvoke (új művelet (setColorTxt), új objektum {i}); Menet. Alvás (250);
if (colorCnts [ismeretlenColorIndex]> 500) {
top. Engaged = hamis; alsó. Engaged = hamis; runtest = hamis; this. BeginInvoke (új művelet (setGoGreen), null); Visszatérés; }}}
private void colourTestBtn_Click (objektumküldő, EventArgs e) {
if (colourTestThread == null ||! colourTestThread. IsAlive) {colourTestThread = new Thread (new ThreadStart (colourTest)); runtest = igaz; colourTestThread. Start (); colourTestBtn. Text = "STOP"; colourTestBtn. BackColor = Szín. Vörös; } else {runtest = hamis; colourTestBtn. Text = "UGRÁS"; colourTestBtn. BackColor = Szín. Zöld; }}
Ezen a ponton van egy munkaprogramunk. Néhány kódrészlet kimaradt a cikkből, ezért nézze meg a forrást a tényleges futtatáshoz.
Második díj az optikai versenyen
Ajánlott:
Arduino - Labirintus megoldó robot (MicroMouse) Falkövető robot: 6 lépés (képekkel)
Arduino | Maze Solving Robot (MicroMouse) Falkövető robot: Üdvözlöm, Isaac vagyok, és ez az első robotom, a "Striker v1.0". Ezt a robotot egy egyszerű labirintus megoldására tervezték. A versenyen két labirintus és a robot volt képes volt azonosítani őket. A labirintusban bekövetkező egyéb változások miatt szükség lehet a
SMARS robot építése - Arduino Smart Robot Tank Bluetooth: 16 lépés (képekkel)
SMARS Robot építése - Arduino Smart Robot Tank Bluetooth: Ezt a cikket büszkén szponzorálja a PCBWAY. A PCBWAY kiváló minőségű prototípus -készítő PCB -ket készít a világ minden tájáról. Próbálja ki Ön is, és szerezzen 10 PCB -t mindössze 5 dollárért a PCBWAY -n, nagyon jó minőségben, köszönöm PCBWAY. A motorpajzs az Arduino Uno -hoz
PAPER HUNGRY ROBOT - Pringles Recycle Arduino Robot: 19 lépés (képekkel)
PAPER HUNGRY ROBOT - Pringles Recycle Arduino Robot: Ez a Hungry Robot egy másik változata, amelyet 2018 -ban építettem. Ezt a robotot 3D nyomtató nélkül is elkészítheti. Csak annyit kell tennie, hogy megvásárol egy doboz Pringles -t, egy szervo motort, egy közelségérzékelőt, egy arduino -t és néhány eszközt. Letöltheti az összes
Joy Robot (Robô Da Alegria) - Nyílt forráskódú 3D nyomtatás, Arduino Powered Robot!: 18 lépés (képekkel)
Joy Robot (Robô Da Alegria) - nyílt forráskódú 3D nyomtatott, Arduino hajtású robot !: Első díj az Instructables Wheels versenyen, második díj az Instructables Arduino versenyen, és második hely a Design for Kids Challenge versenyen. Köszönjük mindenkinek, aki ránk szavazott !!! A robotok mindenhova eljutnak. Az ipari alkalmazásoktól a
Az USB -eszközök rendezése a Laptop segédprogram felületén: 5 lépés
Az USB -eszközök rendezése a Laptop Utility Skin segítségével: A laptop segédprogramja könnyű USB -eszközöket szervez kényelmesen, tépőzárral. A mobil generációk egyikeként szerettem volna megoldani az USB -eszközök helyével és helyével kapcsolatos problémákat. Professzionális és hallgatói újságírás, fotózás, videó és egyéb