Talaan ng mga Nilalaman:

Pag-uuri ng Robotic Bead: 3 Mga Hakbang (na may Mga Larawan)
Pag-uuri ng Robotic Bead: 3 Mga Hakbang (na may Mga Larawan)

Video: Pag-uuri ng Robotic Bead: 3 Mga Hakbang (na may Mga Larawan)

Video: Pag-uuri ng Robotic Bead: 3 Mga Hakbang (na may Mga Larawan)
Video: Узнав это СЕКРЕТ, ты никогда не выбросишь пластиковую бутылку! Идеи для мастерской из бутылок! 2024, Hulyo
Anonim
Image
Image
Pag-uuri ng Robotic Bead
Pag-uuri ng Robotic Bead
Pag-uuri ng Robotic Bead
Pag-uuri ng Robotic Bead
Pag-uuri ng Robotic Bead
Pag-uuri ng Robotic Bead

Sa proyektong ito, magtatayo kami ng isang robot upang pag-uri-uriin ang mga kuwintas ng Perler ayon sa kulay.

Palagi kong nais na bumuo ng isang robot sa pag-uuri ng kulay, kaya't nang interesado ang aking anak na babae sa Perler bead crafting, nakita ko ito bilang isang perpektong pagkakataon.

Ginagamit ang mga perler beads upang lumikha ng mga proyekto sa fuse art sa pamamagitan ng paglalagay ng maraming kuwintas sa isang pegboard, at pagkatapos ay natutunaw ito kasama ng isang bakal. Sa pangkalahatan ay binibili mo ang mga kuwintas na ito sa higanteng 22, 000 kuwintas na halo-halong mga pack ng kulay, at gumugol ng maraming oras sa paghahanap para sa kulay na gusto mo, kaya naisip ko na ang pag-uuri-uriin ang mga ito ay magpapataas sa kahusayan ng sining.

Nagtatrabaho ako para sa Phidgets Inc. kaya't ginamit ko ang karamihan sa Phidgets para sa proyektong ito - ngunit magagawa ito gamit ang anumang naaangkop na hardware.

Hakbang 1: Hardware

Narito ang dati kong itinatayo nito. Itinayo ko ito ng 100% na may mga bahagi mula sa phidgets.com, at mga bagay na nakahiga ako sa paligid ng bahay.

Mga Board ng Phidget, Motors, Hardware

  • HUB0000 - VINT Hub Phidget
  • 1108 - Magnetic Sensor
  • 2x STC1001 - 2.5A Stepper Phidget
  • 2x 3324 - 42STH38 NEMA-17 Bipolar Gearless Stepper
  • 3x 3002 - Phidget Cable 60cm
  • 3403 - USB2.0 4-Port Hub
  • 3031 - Babae Pigtail 5.5x2.1mm
  • 3029 - 2 wire 100 'Twisted Cable
  • 3604 - 10mm White LED (Bag ng 10)
  • 3402 - USB Webcam

Iba pang parte

  • 24VDC 2.0A Power Supply
  • I-scrap ang kahoy at metal mula sa garahe
  • Mga kurbatang zip
  • Plastong lalagyan na may putol sa ilalim

Hakbang 2: Idisenyo ang Robot

Idisenyo ang Robot
Idisenyo ang Robot
Idisenyo ang Robot
Idisenyo ang Robot
Idisenyo ang Robot
Idisenyo ang Robot

Kailangan naming mag-disenyo ng isang bagay na maaaring tumagal ng isang solong bead mula sa input hopper, ilagay ito sa ilalim ng webcam, at pagkatapos ay ilipat ito sa naaangkop na basurahan.

Pickup ng bead

Napagpasyahan kong gawin ang ika-1 bahagi na may 2 piraso ng bilog na playwud, bawat isa ay may isang butas na na-drill sa parehong lugar. Ang ilalim na piraso ay naayos, at ang tuktok na piraso ay nakakabit sa isang stepper motor, na maaaring paikutin ito sa ilalim ng isang hopper na puno ng kuwintas. Kapag ang butas ay naglalakbay sa ilalim ng hopper, nakakakuha ito ng isang solong butil. Maaari ko bang paikutin ito sa ilalim ng webcam, at pagkatapos ay paikutin pa hanggang sa tumugma ito sa butas sa ilalim na piraso, sa oras na ito mahuhulog.

Sa larawang ito, sinusubukan ko na ang system ay maaaring gumana. Ang lahat ay naayos maliban sa tuktok na bilog na piraso ng playwud, na nakakabit sa isang stepper motor na wala sa view sa ilalim. Ang webcam ay hindi pa nai-mount. Gumagamit lang ako ng Phidget Control Panel upang lumiko sa motor sa puntong ito.

Imbakan ng Bead

Ang susunod na bahagi ay ang disenyo ng bin system para sa paghawak ng bawat kulay. Nagpasya akong gumamit ng pangalawang stepper motor sa ibaba upang suportahan at paikutin ang isang bilog na lalagyan na may pantay na puwang na mga compartment. Maaari itong magamit upang paikutin ang tamang kompartimento sa ilalim ng butas na babagsak ng butil.

Itinayo ko ito gamit ang karton at duct tape. Ang pinakamahalagang bagay dito ay ang pagkakapare-pareho - ang bawat kompartimento ay dapat na magkapareho ang laki, at ang buong bagay ay dapat pantay na timbangin upang umikot ito nang hindi lumaktaw.

Ang pagtanggal ng bead ay nagagawa sa pamamagitan ng isang masikip na takip na umaangkop na naglalantad ng isang solong kompartamento nang paisa-isa, upang ang mga kuwintas ay maaaring ibuhos.

Kamera

Ang webcam ay naka-mount sa tuktok na plato sa pagitan ng hopper at ng mas mababang lokasyon ng butas ng plate. Pinapayagan nitong tingnan ng system ang butil bago ihulog ito. Ginagamit ang isang LED upang maipaliwanag ang mga kuwintas sa ilalim ng kamera, at ang ilaw sa paligid ay hinarangan, upang makapagbigay ng isang pare-parehong kapaligiran sa pag-iilaw. Napakahalaga nito para sa tumpak na pagtuklas ng kulay, tulad ng pag-iilaw sa paligid ay maaaring talagang itapon ang pinaghihinalaang kulay.

Pagtuklas ng Lokasyon

Mahalaga para sa system na makita ang pag-ikot ng separator ng bead. Ginagamit ito upang i-set up ang paunang posisyon kapag nagsisimula, ngunit din upang matukoy kung ang stepper motor ay nakuha sa labas ng pag-sync. Sa aking system, ang isang butil ay kung minsan ay masikip habang kinukuha, at ang system na kinakailangan upang makita at hawakan ang sitwasyong ito - sa pamamagitan ng pag-back up ng kaunti at pagsubok ng agian.

Maraming mga paraan upang hawakan ito. Nagpasya akong gumamit ng 1108 magnetic sensor, na may magnet na naka-embed sa gilid ng tuktok na plato. Pinapayagan akong i-verify ang posisyon sa bawat pag-ikot. Ang isang mas mahusay na solusyon ay maaaring isang encoder sa stepper motor, ngunit mayroon akong 1108 na nakahiga kaya ginamit ko iyon.

Tapusin ang Robot

Sa puntong ito, lahat ay nagawa, at nasubukan. Panahon na upang mai-mount nang maayos ang lahat at lumipat sa pagsusulat ng software.

Ang 2 stepper motors ay hinihimok ng mga STC1001 stepper Controller. Ang isang HUB000 - Ang USB VINT hub ay ginagamit para sa pagpapatakbo ng mga stepper Controller, pati na rin ang pagbabasa ng magnetic sensor at pagmamaneho ng LED. Ang webcam at HUB0000 ay parehong naka-attach sa isang maliit na USB hub. Ang isang 3031 pigtail at ilang kawad ay ginagamit kasama ang isang 24V power supply upang paandarin ang mga motor.

Hakbang 3: Sumulat ng Code

Image
Image

Ginagamit ang C # at Visual Studio 2015 para sa proyektong ito. I-download ang mapagkukunan sa tuktok ng pahinang ito at sundin - ang mga pangunahing seksyon ay nakabalangkas sa ibaba

Pasimula

Una, dapat nating likhain, buksan at simulan ang mga bagay na Phidget. Ginagawa ito sa kaganapan sa pag-load ng form, at ang mga handler ng Phidget na magkabit.

pribadong walang bisa na Form1_Load (nagpadala ng object, EventArgs e) {

/ * Ipasimula at buksan ang Mga Phidget * /

tuktok. HubPort = 0; tuktok. Attach + = Top_Attach; top. Detach + = Top_Detach; tuktok. PositionChange + = Top_PositionChange; itaas. Buksan ();

ilalim. HubPort = 1;

sa ibaba. Attach + = Ibaba_Attach; ilalim. Detach + = Bottom_Detach; ilalim. PositionChange + = Ibaba_PositionChange; ibaba. Buksan ();

magSensor. HubPort = 2;

magSensor. IsHubPortDevice = totoo; magSensor. Attach + = MagSensor_Attach; magSensor. Detach + = MagSensor_Detach; magSensor. SensorChange + = MagSensor_SensorChange; magSensor. Open ();

humantong. HubPort = 5;

led. IsHubPortDevice = totoo; led. Channel = 0; humantong. Attach + = Led_Attach; led. Detach + = Led_Detach; pinangunahan. Buksan (); }

pribadong void Led_Attach (nagpadala ng object, Phidget22. Events. AttachEventArgs e) {

ledAttachedChk. Checked = totoo; led. State = totoo; ledChk. Checked = totoo; }

pribadong walang bisa MagSensor_Attach (nagpadala ng object, Phidget22. Events. AttachEventArgs e) {

magSensorAttachedChk. Checked = totoo; magSensor. SensorType = VoltageRatioSensorType. PN_1108; magSensor. DataInterval = 16; }

pribadong void Bottom_Attach (nagpadala ng object, Phidget22. Events. AttachEventArgs e) {

ilalimAttachedChk. Checked = totoo; ilalim. CurrentLimit = ilalimCurrentLimit; ilalim. Engaged = totoo; ilalim. VelocityLimit = ilalimVelocityLimit; ilalim. Pagpabilis = ilalimAccel; ilalim. DataInterval = 100; }

pribadong walang bisa Top_Attach (nagpadala ng object, Phidget22. Events. AttachEventArgs e) {

topAttachedChk. Checked = totoo; tuktok. CurrentLimit = topCurrentLimit; tuktok. Engaged = totoo; tuktok. RescaleFactor = -1; tuktok. VelocityLimit = -topVelocityLimit; tuktok. Pagpabilis = -topAccel; itaas. DataInterval = 100; }

Nabasa din namin ang anumang nai-save na impormasyon ng kulay sa panahon ng pagsisimula, kaya't ang isang nakaraang pagtakbo ay maaaring ipagpatuloy.

Pagpoposisyon ng Motor

Ang code sa paghawak ng motor ay binubuo ng mga pagpapaandar sa kaginhawaan para sa paglipat ng mga motor. Ang mga motor na ginamit ko ay 3, 200 1 / 16th na mga hakbang sa bawat rebolusyon, kaya't gumawa ako ng pare-pareho para dito.

Para sa nangungunang motor, mayroong 3 mga posisyon na nais naming maipadala sa motor sa: webcam, butas, at pang-posisyon ng pang-akit. Mayroong isang pagpapaandar para sa paglalakbay sa bawat isa sa mga posisyon na ito:

pribadong void nextMagnet (Boolean wait = false) {

doble posn = tuktok. Posisyon% mga hakbangPerRev;

top. TargetPosition + = (stepsPerRev - posn);

kung (maghintay)

habang (itaas. Gumagalaw) Thread. Tulog (50); }

pribadong walang bisa sa susunodCamera (Boolean wait = false) {

doble posn = tuktok. Posisyon% mga hakbangPerRev; kung (posn <Properties. Settings. Default.cameraOffset) sa itaas. TargetPosition + = (Properties. Settings. Default.cameraOffset - posn); iba pa sa itaas. TargetPosition + = ((Properties. Settings. Default.cameraOffset - posn) + stepsPerRev);

kung (maghintay)

habang (itaas. Gumagalaw) Thread. Tulog (50); }

pribadong void nextHole (Boolean wait = false) {

doble posn = tuktok. Posisyon% mga hakbangPerRev; kung (posn <Properties. Settings. Default.holeOffset) sa itaas. TargetPosition + = (Properties. Settings. Default.holeOffset - posn); iba pa sa itaas. TargetPosition + = ((Properties. Settings. Default.holeOffset - posn) + stepsPerRev);

kung (maghintay)

habang (itaas. Gumagalaw) Thread. Tulog (50); }

Bago simulan ang isang run, ang tuktok na plato ay nakahanay gamit ang magnetic sensor. Ang pag-andar ng alignMotor ay maaaring tawagan sa anumang oras upang ihanay ang tuktok na plato. Ang pagpapaandar na ito ay unang mabilis na pinaliliko ang plate hanggang sa 1 buong rebolusyon hanggang sa makita nito ang data ng magnet sa itaas ng isang threshold. Pagkatapos ay nai-back up ito nang kaunti at gumagalaw muli nang dahan-dahan, kinukuha ang data ng sensor sa paglipas nito. Sa wakas, itinatakda nito ang posisyon sa maximum na lokasyon ng data ng magnet, at itinatakda ang posisyon na nakabalanse sa 0. Samakatuwid, ang posisyon ng max na magnet ay dapat palaging nasa (itaas. Posisyon% mga hakbangPerRev)

Thread alignMotorThread; Boolean sawMagnet; doble magSensorMax = 0; pribadong void alignMotor () {

// Hanapin ang pang-akit

top. DataInterval = itaas. MinDataInterval;

sawMagnet = false;

magSensor. SensorChange + = magSensorStopMotor; tuktok. VelocityLimit = -1000;

int tryCount = 0;

tryagain:

tuktok. TargetPosition + = stepsPerRev;

habang (tuktok. IsMoving &&! sawMagnet) Thread. Sulog (25);

kung (! sawMagnet) {

kung (tryCount> 3) {Console. WriteLine ("Nabigo ang pagkakahanay"); tuktok. Engaged = false; ilalim. Engaged = false; runtest = false; bumalik; }

tryCount ++;

Console. WriteLine ("Naka-stuck ba kami? Sinusubukan ang isang backup …"); tuktok. TargetPosition - = 600; habang (itaas. Gumagalaw) Thread. Tulog (100);

goto tryagain;

}

tuktok. VelocityLimit = -100;

magData = bagong Listahan> (); magSensor. SensorChange + = magSensorCollectPositionData; tuktok. TargetPosition + = 300; habang (itaas. Gumagalaw) Thread. Tulog (100);

magSensor. SensorChange - = magSensorCollectPositionData;

tuktok. VelocityLimit = -topVelocityLimit;

KeyValuePair max = magData [0];

maaga (pares ng KeyValuePair sa magData) kung (pares. Value> max. Value) max = pares;

tuktok. AddPositionOffset (-max. Key);

magSensorMax = max. Value;

tuktok. TargetPosition = 0;

habang (itaas. Gumagalaw) Thread. Tulog (100);

Console. WriteLine ("Nagtagumpay na ihanay");

}

Listahan> magData;

pribadong void magSensorCollectPositionData (object sender, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {magData. Add (bagong KeyValuePair (top. Position, e. SensorValue)); }

pribadong void magSensorStopMotor (nagpadala ng object, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {

kung (top. IsMoving && e. SensorValue> 5) {top. TargetPosition = top. Position - 300; magSensor. SensorChange - = magSensorStopMotor; sawMagnet = totoo; }}

Panghuli, ang ilalim ng motor ay kinokontrol ng pagpapadala nito sa isa sa mga posisyon ng lalagyan ng bead. Para sa proyektong ito, mayroon kaming 19 na posisyon. Ang algorithm ay pipili ng isang pinakamaikling landas, at liliko alinman sa pakanan o pakaliwa.

pribadong int BottomPosition {makakuha {int posn = (int) sa ibaba. Posisyon% hakbangPerRev; kung (posn <0) posn + = stepsPerRev;

ibalik (int) Math. Round (((posn * beadCompartments) / (doble) na mga hakbangPerRev));

} }

pribadong walang bisa ang SetBottomPosition (int posn, bool wait = false) {

posn = posn% beadCompartments; double targetPosn = (posn * stepsPerRev) / beadCompartments;

doble kasalukuyangPosn = ibaba. Posisyon% mga hakbangPerRev;

doble posnDiff = targetPosn - kasalukuyangPosn;

// Panatilihin ito bilang buong mga hakbang

posnDiff = ((int) (posnDiff / 16)) * 16;

kung (posnDiff <= 1600) sa ibaba. TargetPosition + = posnDiff; iba pa sa ibaba. TargetPosition - = (stepsPerRev - posnDiff);

kung (maghintay)

habang (ilalim. Pagmamaneho) Thread. Tulog (50); }

Kamera

Ginagamit ang OpenCV upang basahin ang mga imahe mula sa webcam. Sinimulan ang thread ng camera bago simulan ang pangunahing thread ng pag-uuri. Patuloy na binabasa ng thread na ito ang mga imahe, kinakalkula ang isang average na kulay para sa isang tukoy na rehiyon gamit ang Min at ina-update ang isang pandaigdigang variable ng kulay. Gumagamit din ang thread ng HoughCircles upang subukang makita ang alinman sa isang butil, o ang butas sa tuktok na plato, upang pinuhin ang lugar na tinitingnan nito para sa pagtuklas ng kulay. Ang mga numero ng threshold at HoughCircles ay natutukoy sa pamamagitan ng pagsubok at error, at nakasalalay nang husto sa webcam, ilaw, at spacing.

bool runVideo = true; bool videoRunning = false; Nakunan ng VideoCapture; Thread cvThread; Nakita ang kulayKulay; Ang pagtuklas ng Boolean = false; int detectCnt = 0;

pribadong void cvThreadFunction () {

videoRunning = false;

makunan = bagong VideoCapture (napiliCamera);

gamit ang (Window window = bagong Window ("capture")) {

Mat image = bagong Mat (); Mat image2 = bagong Mat (); habang (runVideo) {capture. Read (imahe); kung (image. Edomy ()) masira;

kung (nakakakita)

nakitaCnt ++; sino pa man ang makitaCnt = 0;

kung (nakakakita || circleDetectChecked || showDetectionImgChecked) {

Cv2. CvtColor (imahe, imahe2, ColorConversionCodes. BGR2GRAY); Mat thres = image2. Threshold ((doble) Mga Properties. Settings. Default.videoThresh, 255, ThresholdTypes. Binary); thres = thres. GaussianBlur (bagong OpenCvSharp. Size (9, 9), 10);

kung (showDetectionImgChecked)

imahe = thres;

kung (tiktikan || circleDetectChecked) {

CircleSegment bead = thres. HoughCircles (HoughMethods. Gradient, 2, /*thres. Rows/4*/ 20, 200, 100, 20, 65); kung (bead. Length> = 1) {image. Circle (bead [0]. Center, 3, bagong Scalar (0, 100, 0), -1); imahe. Circle (bead [0]. Center, (int) bead [0]. Radius, bagong Scalar (0, 0, 255), 3); kung (butil [0]. Radius> = 55) {Properties. Settings. Default.x = (decimal) bead [0]. Center. X + (decimal) (bead [0]. Radius / 2); Mga Katangian. Settings. Default.y = (decimal) bead [0]. Center. Y - (decimal) (bead [0]. Radius / 2); } iba pa {Properties. Settings. Default.x = (decimal) bead [0]. Center. X + (decimal) (bead [0]. Radius); Mga Katangian. Settings. Default.y = (decimal) bead [0]. Center. Y - (decimal) (bead [0]. Radius); } Mga Katangian. Settings. Default.size = 15; Mga Katangian. Settings. Default.height = 15; } iba pa {

CircleSegment bilog = thres. HoughCircles (HoughMethods. Gradient, 2, /*thres. Rows/4*/ 5, 200, 100, 60, 180);

kung (circle. Length> 1) {List xs = circle. Select (c => c. Center. X). ToList (); xs. Sort (); Listahan ys = bilog. Piliin (c => c. Center. Y). ToList (); ys. Sort ();

int medianX = (int) xs [xs. Count / 2];

int medianY = (int) ys [ys. Count / 2];

kung (medianX> imahe. Malalim - 15)

medianX = imahe. Width - 15; kung (medianY> imahe. Taas - 15) medianY = imahe. Taas - 15;

imahe. Circle (medianX, medianY, 100, bagong Scalar (0, 0, 150), 3);

kung (nakita) {

Mga Katangian. Settings. Default.x = medianX - 7; Mga Katangian. Settings. Default.y = medianY - 7; Mga Katangian. Settings. Default.size = 15; Mga Katangian. Settings. Default.height = 15; }}}}}

Rect r = bagong Rect ((int) Properties. Settings. Default.x, (int) Properties. Settings. Default.y, (int) Properties. Settings. Default.size, (int) Properties. Settings. Default.height);

Mat beadSample = bagong Mat (imahe, r);

Scalar avgColor = Cv2. Mean (beadSample); napansinColor = Kulay. FromArgb ((int) avgColor [2], (int) avgColor [1], (int) avgColor [0]);

imahe. Rectangle (r, bagong Scalar (0, 150, 0));

window. ShowImage (imahe);

Cv2. WaitKey (1); videoRunning = totoo; }

videoRunning = false;

} }

pribadong void cameraStartBtn_Click (nagpadala ng object, EventArgs e) {

kung (cameraStartBtn. Text == "start") {

cvThread = bagong Thread (bagong ThreadStart (cvThreadFunction)); runVideo = totoo; cvThread. Sartart (); cameraStartBtn. Text = "stop"; habang (! videoRunning) Thread. Tulog (100);

updateColorTimer. Start ();

} iba pa {

runVideo = false; cvThread. Join (); cameraStartBtn. Text = "start"; }}

Kulay

Ngayon, nagagawa naming matukoy ang kulay ng isang butil, at magpasya batay sa kulay na iyon sa aling lalagyan na ihuhulog ito.

Ang hakbang na ito ay nakasalalay sa paghahambing ng kulay. Nais naming makapagkuwento ng mga kulay upang malimitahan ang maling positibo, ngunit papayagan din ang sapat na threshold upang limitahan ang mga maling negatibo. Ang paghahambing ng mga kulay ay talagang nakakagulat na kumplikado, sapagkat ang paraan ng pag-iimbak ng mga computer ng mga kulay bilang RGB, at ang paraan ng pag-iisip ng mga tao ng mga kulay ay hindi nauugnay nang tuwid. Upang mapalala ang mga bagay, ang kulay ng ilaw na isang kulay ay tiningnan sa ilalim din ay dapat isaalang-alang.

Mayroong mga kumplikadong algorithm para sa pagkalkula ng pagkakaiba sa kulay. Gumagamit kami ng CIE2000, na naglalabas ng isang numero na malapit sa 1 kung ang 2 mga kulay ay hindi makikilala sa isang tao. Gumagamit kami ng library ng ColorMine C # upang gawin ang mga kumplikadong kalkulasyon na ito. Ang isang halaga ng DeltaE na 5 ay natagpuan upang mag-alok ng isang mahusay na kompromiso sa pagitan ng maling positibo at maling negatibo.

Tulad ng madalas na mas maraming mga kulay pagkatapos ng mga lalagyan, ang huling posisyon ay nakalaan bilang isang catchall bin. Sa pangkalahatan ay itinabi ko ang mga ito upang tumakbo kahit na ang makina sa isang pangalawang pass.

Listahan

kulay = bagong Listahan (); Listahan ng colorPanels = bagong List (); Listahan ng mga kulayTxt = bagong Listahan (); Listahan ng colorCnts = bagong Listahan ();

const int numColorSpot = 18;

Const int unknownColorIndex = 18; int findColorPosition (Kulay c) {

Console. WriteLine ("Paghahanap ng kulay …");

var cRGB = bagong Rgb ();

cRGB. R = c. R; cRGB. G = c. G; cRGB. B = c. B;

int bestMatch = -1;

doble na tugmaDelta = 100;

para sa (int i = 0; i <color. Count; i ++) {

var RGB = bagong Rgb ();

RGB. R = mga kulay . R; RGB. G = mga kulay . G; RGB. B = mga kulay . B;

double delta = cRGB. Compare (RGB, bagong CieDe2000Comparison ());

// double delta = deltaE (c, mga kulay ); Console. WriteLine ("DeltaE (" + i. ToString () + "):" + delta. ToString ()); kung (delta <matchDelta) {matchDelta = delta; bestMatch = i; }}

kung (matchDelta <5) {Console. WriteLine ("Nahanap! (Posn:" + bestMatch + "Delta:" + matchDelta + ")"); bumalik bestMatch; }

kung (color. Count <numColorSpot) {Console. WriteLine ("Bagong Kulay!"); mga kulay. Idagdag (c); this. BeginInvoke (bagong Pagkilos (setBackColor), bagong object {color. Count - 1}); magsulatOutColors (); pagbalik (mga kulay. Bilang - 1); } iba pa {Console. WriteLine ("Hindi Kilalang Kulay!"); bumalik hindi alamColorIndex; }}

Pag-uuri ng Lohika

Pinagsasama-sama ng pagpapaandar ng pag-uuri ang lahat ng mga piraso upang talagang ayusin ang mga kuwintas. Ang pagpapaandar na ito ay tumatakbo sa isang nakalaang thread; paglipat ng tuktok na plato, nakita ang kulay ng butil, inilalagay ito sa isang basurahan, tinitiyak na ang tuktok na plato ay mananatiling nakahanay, binibilang ang mga kuwintas, atbp. Humihinto din ito sa pagtakbo kapag ang catchall bin ay puno - Kung hindi man ay nagtatapos lamang tayo sa mga umaapaw na kuwintas.

Thread colourTestThread; Boolean runtest = false; void colourTest () {

kung (! nangunguna. Na-engganyo)

tuktok. Engaged = totoo;

kung (! ilalim. Nakipag-usap)

ilalim. Engaged = totoo;

habang (runtest) {

susunodMagnet (totoo);

Thread. Tulog (100); subukan ang {if (magSensor. SensorValue <(magSensorMax - 4)) alignMotor (); } mahuli ang {alignMotor (); }

susunodCamera (totoo);

tiktik = totoo;

habang (tiktikCnt <5) Thread. Tulog (25); Console. WriteLine ("Detect Count:" + detectCnt); detecting = false;

Kulay c = nakitaColor;

this. BeginInvoke (bagong Pagkilos (setColorDet), bagong object {c}); int i = findColorPosition (c);

SetBottomPosition (i, totoo);

susunodHole (totoo); colorCnts ++; this. BeginInvoke (bagong Pagkilos (setColorTxt), bagong object {i}); Thread. Tulog (250);

kung (colorCnts [unknownColorIndex]> 500) {

tuktok. Engaged = false; ilalim. Engaged = false; runtest = false; ito. BeginInvoke (bagong Pagkilos (setGoGreen), null); bumalik; }}}

pribadong void colourTestBtn_Click (nagpadala ng object, EventArgs e) {

kung (colourTestThread == null ||! colourTestThread. IsAlive) {colourTestThread = bagong Thread (bagong ThreadStart (colourTest)); runtest = totoo; colourTestThread. Sart (); colourTestBtn. Text = "STOP"; colourTestBtn. BackColor = Kulay. Red; } iba pa {runtest = false; colourTestBtn. Text = "GO"; colourTestBtn. BackColor = Kulay. Green; }}

Sa puntong ito, mayroon kaming isang gumaganang programa. Ang ilang mga piraso ng code ay naiwan sa artikulo, kaya't tingnan ang mapagkukunan upang patakbuhin ito.

Paligsahan sa Optics
Paligsahan sa Optics

Pangalawang Gantimpala sa Paligsahan sa Optika

Inirerekumendang: