Mundarija:

Boncuklarni robotlashtirish: 3 qadam (rasmlar bilan)
Boncuklarni robotlashtirish: 3 qadam (rasmlar bilan)

Video: Boncuklarni robotlashtirish: 3 qadam (rasmlar bilan)

Video: Boncuklarni robotlashtirish: 3 qadam (rasmlar bilan)
Video: Зайка "Не-влезайка". Авторскя игрушка Ирины Земской. Заключительная часть. 2024, Iyul
Anonim
Image
Image
Boncukli robotlarni saralash
Boncukli robotlarni saralash
Boncukli robotlarni saralash
Boncukli robotlarni saralash
Boncukli robotlarni saralash
Boncukli robotlarni saralash

Ushbu loyihada biz Perler boncuklarini rang bo'yicha saralash uchun robot quramiz.

Men har doim ranglarni ajratuvchi robot yaratmoqchi edim, shuning uchun qizim Perlerdan boncuk yasashga qiziqib qolganida, men buni ajoyib imkoniyat deb bildim.

Perler munchoqlari ko'plab munchoqlarni qoziq taxtasiga qo'yib, keyin ularni temir bilan eritib, birlashtirilgan san'at loyihalarini yaratish uchun ishlatiladi. Siz odatda bu boncuklarni 22 000 dona boncukli aralash paketlarda sotib olasiz va kerakli rangni qidirishga ko'p vaqt sarflaysiz, shuning uchun ularni saralash san'at samaradorligini oshiradi deb o'yladim.

Men Phidgets Inc.da ishlayman, shuning uchun men ushbu loyihada asosan Phidgets -dan foydalanardim, lekin buni har qanday mos keladigan uskuna yordamida amalga oshirish mumkin edi.

1 -qadam: Uskuna

Mana, men buni oldin qurganman. Men uni 100% phidgets.com saytining qismlari va uy atrofida yotgan narsalarim bilan qurdim.

Fidjetlar taxtasi, motorlar, apparat

  • HUB0000 - VINT Hub vidjeti
  • 1108 - magnit sensor
  • 2x STC1001 - 2,5A qadamli vidjet
  • 2x 3324 - 42STH38 NEMA -17 bipolyar tishli holda
  • 3x 3002 - Phidget kabeli 60 sm
  • 3403 - USB2.0 4 -portli uyadan
  • 3031 - urg'ochi cho'chqa go'shti 5,5x2,1 mm
  • 3029 - 2 simli 100 'o'ralgan kabel
  • 3604 - 10 mm oq LED (10 ta sumka)
  • 3402 - USB veb -kamerasi

Boshqa qismlar

  • 24VDC 2.0A quvvat manbai
  • Garajdan yog'och va metallni olib tashlang
  • Fermuar bog'lamlari
  • Pastki qismi kesilgan plastik idish

2 -qadam: Robotni loyihalash

Robotni loyihalash
Robotni loyihalash
Robotni loyihalash
Robotni loyihalash
Robotni loyihalash
Robotni loyihalash

Biz kirish shkafidan bitta boncuk oladigan, uni veb -kameraning ostiga qo'yadigan va keyin uni tegishli qutiga ko'chiradigan narsalarni loyihalashimiz kerak.

Boncuk olish

Men 1 -qismni 2 dona dumaloq kontrplak bilan bajarishga qaror qildim, ularning har biri bir joyda teshilgan. Pastki qismi mahkamlangan, ustki qismi esa zanjirli dvigatelga ulangan, uni boncuklar bilan to'ldirilgan huni tagida aylantirish mumkin. Teshik huni tagida harakat qilganda, u bitta boncuk oladi. Keyin men uni veb -kamera ostida aylantira olaman, so'ngra pastki qismidagi teshikka to'g'ri kelgunga qadar aylantira olaman, shu vaqtda u tushadi.

Bu rasmda men tizim ishlay olishini sinovdan o'tkazyapman. Hamma narsa pog'onali dvigatelning ostidan ko'rinmas holda biriktirilgan kontrplakning yuqori dumaloq bo'lagidan boshqa hamma narsa tuzatilgan. Veb -kamera hali o'rnatilmagan. Men hozirda dvigatelga o'tish uchun Phidget boshqaruv panelidan foydalanayapman.

Boncuklarni saqlash

Keyingi qism - har bir rangni saqlash uchun axlat qutisi tizimini loyihalash. Tegishli bo'linmali dumaloq idishni qo'llab -quvvatlash va aylantirish uchun men quyida ikkinchi qadamli dvigatelni ishlatishga qaror qildim. Bu boncuk tushadigan teshik ostidagi to'g'ri bo'linmani aylantirish uchun ishlatilishi mumkin.

Men buni karton va yopishqoq lenta yordamida qurdim. Bu erda eng muhim narsa - bu mustahkamlik - har bir bo'linma bir xil o'lchamda bo'lishi kerak va hamma narsa bir xil og'irlikda bo'lishi kerak, shunda u o'tkazib yubormasdan aylanadi.

Boncuklarni olib tashlash mahkam yopilgan qopqoq yordamida amalga oshiriladi, u bir vaqtning o'zida bitta bo'lakni ochadi, shuning uchun boncuklarni to'kish mumkin.

Kamera

Veb -kamera ustki plastinka ustki ustuni bilan pastki plastinka teshigining orasiga o'rnatiladi. Bu tizimga boncukni tushirishdan oldin qarashga imkon beradi. Kamera ostidagi munchoqlarni yoritish uchun LED ishlatiladi va doimiy yorug'lik muhitini ta'minlash uchun atrofdagi yorug'lik bloklanadi. Bu rangni aniq aniqlash uchun juda muhim, chunki atrofdagi yorug'lik haqiqatan ham qabul qilingan rangni yo'qotishi mumkin.

Joyni aniqlash

Tizim uchun boncuk ajratgichning aylanishini aniqlay olish juda muhimdir. Bu ishga tushirish paytida boshlang'ich pozitsiyasini o'rnatish uchun, shuningdek, step motorining sinxronlashdan chiqqanligini aniqlash uchun ishlatiladi. Mening tizimimda, munchoq olganda, ba'zida tiqilib qoladi va tizim bu holatni aniqlay olishi va hal qila olishi kerak edi - biroz zaxiralash va agianni sinab ko'rish.

Buni hal qilishning ko'plab usullari mavjud. Men yuqori plastinkaning chetiga o'rnatilgan magnitli 1108 magnitli sensorni ishlatishga qaror qildim. Bu menga har bir aylanishdagi pozitsiyani tekshirishga imkon beradi. Yaxshi echim, ehtimol, step motoridagi kodlovchi bo'lardi, lekin menda 1108 yotardi, shuning uchun men uni ishlatardim.

Robotni tugating

Bu vaqtda hamma narsa ishlab chiqilgan va sinovdan o'tgan. Hamma narsani yaxshi o'rnatish va dasturiy ta'minotga o'tish vaqti keldi.

2 bosqichli dvigatellar STC1001 pog'onali boshqaruvchilari tomonidan boshqariladi. HUB000 - USB VINT uyasi qadamni boshqarish moslamalarini ishga tushirish, shuningdek magnitli sensorni o'qish va LEDni boshqarish uchun ishlatiladi. Veb -kamera va HUB0000 ikkalasi ham kichik USB uyasiga ulangan. Dvigatellarni quvvatlantirish uchun 24 V kuchlanishli quvvat manbai bilan bir qatorda 3031 cho'chqa va ba'zi simlar ishlatiladi.

3 -qadam: Kod yozing

Image
Image

Ushbu loyiha uchun C# va Visual Studio 2015 ishlatiladi. Sahifaning yuqori qismidagi manbani yuklab oling va davom eting - asosiy bo'limlar quyida keltirilgan

Boshlash

Birinchidan, biz Phidget ob'ektlarini yaratishimiz, ochishimiz va ishga tushirishimiz kerak. Bu formani yuklash hodisasida amalga oshiriladi va Phidget biriktiruvchi ishlovchilar.

shaxsiy bo'shliq Form1_Load (ob'ekt yuboruvchi, EventArgs e) {

/ * Fidjetlarni ishga tushiring va oching */

top. HubPort = 0; top. Attach += Top_Attach; top. Detach += Top_Detach; top. PositionChange += Top_PositionChange; top. Open ();

pastki. HubPort = 1;

pastki. Attach += Bottom_Attach; pastki. Detach += Bottom_Detach; pastki. PositionChange += Bottom_PositionChange; pastki Ochiq ();

magSensor. HubPort = 2;

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

led. HubPort = 5;

led. IsHubPortDevice = rost; LED kanal = 0; led. Attach += Led_Attach; led. Detach += Led_Detach; led. Open (); }

shaxsiy bo'shliq Led_Attach (ob'ekt yuboruvchi, Phidget22. Events. AttachEventArgs e) {

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

shaxsiy bo'shliq MagSensor_Attach (ob'ekt yuboruvchi, Phidget22. Events. AttachEventArgs e) {

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

shaxsiy bo'shliq Bottom_Attach (ob'ekt yuboruvchi, Phidget22. Events. AttachEventArgs e) {

bottomAttachedChk. Checked = rost; pastki. CurrentLimit = bottomCurrentLimit; pastki. Engaged = rost; pastki. VelocityLimit = bottomVelocityLimit; pastki Tezlik = bottomAccel; pastki. DataInterval = 100; }

shaxsiy bo'shliq Top_Attach (ob'ekt yuboruvchi, Phidget22. Events. AttachEventArgs e) {

topAttachedChk. Checked = rost; top. CurrentLimit = topCurrentLimit; top. Engaged = rost; top. RescaleFactor = -1; top. VelocityLimit = -topVelocityLimit; top. Akseleratsiya = -topAccel; top. DataInterval = 100; }

Biz, shuningdek, ishga tushirish paytida saqlangan rangli ma'lumotlarni o'qiymiz, shuning uchun oldingi ishga tushirishni davom ettirish mumkin.

Dvigatel joylashuvi

Dvigatelni boshqarish kodi dvigatellarni harakatlantirish uchun qulaylik funktsiyalaridan iborat. Men ishlatgan dvigatellar har bir inqilobda 3 200 ta 1/16 qadamdir, shuning uchun men doimiyni yaratdim.

Yuqori dvigatel uchun biz motorga yuborishimiz kerak bo'lgan 3 pozitsiya mavjud: veb -kamera, teshik va joylashishni aniqlash magnitlari. Ushbu pozitsiyalarning har biriga sayohat qilish funktsiyasi mavjud:

nextMagnet shaxsiy bo'shligi (mantiqiy kutish = noto'g'ri) {

double posn = top. Position % stepsPerRev;

top. TargetPosition += (stepsPerRev - posn);

agar (kuting)

while (top. IsMoving) Thread. Sleep (50); }

private void nextCamera (Boolean wait = false) {

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);

agar (kuting)

while (top. IsMoving) Thread. Sleep (50); }

nextHole shaxsiy bo'sh joy (mantiqiy kutish = noto'g'ri) {

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);

agar (kuting)

while (top. IsMoving) Thread. Sleep (50); }

Yugurishni boshlashdan oldin, yuqori plastinka magnit sensor yordamida tekislanadi. AlignMotor funktsiyasini istalgan vaqtda yuqori plastinkani tekislash uchun chaqirish mumkin. Bu funktsiya, birinchi navbatda, plastinkani magnit ma'lumotlarini pol ostidan ko'rmaguncha, 1 to'liq aylanishga aylantiradi. Keyin u bir oz orqaga qaytadi va asta -sekin oldinga siljiydi va sensorlar ma'lumotlarini ushlab turadi. Nihoyat, u pozitsiyani magnitlangan ma'lumotlarning maksimal joylashuviga o'rnatadi va o'rnini 0 ga qaytaradi. Shunday qilib, magnitning maksimal joylashuvi har doim bo'lishi kerak (tepada. % QadamPerRev pozitsiyasi).

Mavzuni tekislashMotorThread; Boolean sawMagnet; er -xotin magSensorMax = 0; shaxsiy bo'shliq alignMotor () {

// Magnitni toping

top. DataInterval = top. MinDataInterval;

sawMagnet = noto'g'ri;

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

int tryCount = 0;

qayta urinib ko'ring:

top. TargetPosition += stepsPerRev;

while (top. IsMoving &&! sawMagnet) Thread. Sleep (25);

agar (! sawMagnet) {

if (tryCount> 3) {Console. WriteLine ("Hizalanmadi"); top. Engaged = false; pastki. Engaged = false; runtest = noto'g'ri; qaytish; }

tryCount ++;

Console. WriteLine ("Biz qolib ketdikmi? Zaxira nusxasini qidirmoqdamiz …"); top. TargetPosition -= 600; while (top. IsMoving) Thread. Sleep (100);

qayta urinish kerak;

}

top. VelocityLimit = -100;

magData = yangi ro'yxat> (); magSensor. SensorChange += magSensorCollectPositionData; top. TargetPosition += 300; while (top. IsMoving) Thread. Sleep (100);

magSensor. SensorChange -= magSensorCollectPositionData;

top. VelocityLimit = -topVelocityLimit;

KeyValuePair max = magData [0];

foreach (magData -dagi KeyValuePair juftligi) if (pair. Value> max. Value) max = pair;

top. AddPositionOffset (-max kalit);

magSensorMax = maksimal qiymat;

top. TargetPosition = 0;

while (top. IsMoving) Thread. Sleep (100);

Console. WriteLine ("Align muvaffaq bo'ldi");

}

Ro'yxat> magData;

maxfiy bo'sh magSensorCollectPositionData (ob'ekt yuboruvchi, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {magData. Add (yangi KeyValuePair (top. Position, e. SensorValue))); }

magSensorStopMotor xususiy bo'sh joy (ob'ektni jo'natuvchi, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {

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

Nihoyat, pastki dvigatel, uni boncuk konteyner pozitsiyalaridan biriga yuborish orqali boshqariladi. Ushbu loyiha uchun bizda 19 ta pozitsiya mavjud. Algoritm eng qisqa yo'lni tanlaydi va soat yo'nalishi bo'yicha yoki teskari yo'nalishda aylanadi.

private int BottomPosition {get {int posn = (int) bottom. Position % stepsPerRev; agar (posn <0) posn += stepsPerRev;

return (int) Math. Round (((posn * beadCompartments) / (double) stepsPerRev));

} }

Maxsus bo'sh joy SetBottomPosition (int posn, bool wait = false) {

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

ikki tomonlama

er -xotin posnDiff = targetPosn - currentPosn;

// Buni to'liq qadamlar sifatida saqlang

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

if (posnDiff <= 1600) pastki. TargetPosition += posnDiff; else bottom. TargetPosition - = (stepsPerRev - posnDiff);

agar (kuting)

while (bottom. IsMoving) Thread. Sleep (50); }

Kamera

OpenCV veb -kameradan rasmlarni o'qish uchun ishlatiladi. Kamera chizig'i asosiy saralash ipini ishga tushirishdan oldin boshlanadi. Bu mavzu doimiy ravishda rasmlarda o'qiladi, o'rtacha yordamida ma'lum bir mintaqaning o'rtacha rangini hisoblab chiqadi va global rang o'zgaruvchisini yangilaydi. Ip, shuningdek, boncukni yoki yuqori plastinkadagi teshikni aniqlashga harakat qilib, rangni aniqlaydigan maydonni aniqlab beradi. Eshik va HoughCircles raqamlari sinov va xato orqali aniqlandi va ko'p jihatdan veb -kameraga, yorug'lik va intervalga bog'liq.

bool runVideo = rost; bool videoRunning = noto'g'ri; Video ta'qib qilish; Mavzu cvThread; Rang aniqlandi; Mantiqiy aniqlash = noto'g'ri; int detectCnt = 0;

maxfiy vv cvThreadFunction () {

videoRunning = noto'g'ri;

ta'qib qilish = yangi VideoCapture (selectedCamera);

yordamida (Oyna oynasi = yangi oyna ("yozib olish")) {

Mat tasviri = yangi Mat (); Mat image2 = yangi Mat (); while (runVideo) {capture. Read (rasm); if (image. Empty ()) buzilsa;

agar (aniqlansa)

aniqlashCnt ++; boshqa aniqlashCnt = 0;

if (aniqlash || CircleDetectChecked || showDetectionImgChecked) {

Cv2. CvtColor (rasm, image2, ColorConversionCodes. BGR2GRAY); Mat thres = image2. Threshold ((double) Properties. Settings. Default.videoThresh, 255, ThresholdTypes. Binary); thres = thres. GaussianBlur (yangi OpenCvSharp. Size (9, 9), 10);

agar (showDetectionImgChecked)

tasvir = thres;

agar (aniqlansa || CircleDetectChecked) {

CircleSegment bead = thres. HoughCircles (HoughMethods. Gradient, 2, /*thres. Rows/4*/ 20, 200, 100, 20, 65); if (munchoq. Length> = 1) {image. Circle (boncuk [0]. Markaz, 3, yangi Skalyar (0, 100, 0), -1); tasvir. Circle (munchoq [0]. Markaz, (int) boncuk [0]. Radius, yangi Skalyar (0, 0, 255), 3); if (bead [0]. Radius> = 55) {Properties. Settings. Default.x = (o'nlik) munchoq [0]. Center. X + (o'nlik) (boncuk [0]. Radius / 2); Properties. Settings. Default.y = (o'nlik) boncuk [0]. Center. Y - (o'nlik) (boncuk [0]. Radius / 2); } else {Properties. Settings. Default.x = (o'nlik) boncuk [0]. Center. X + (o'nlik) (boncuk [0]. Radius); Properties. Settings. Default.y = (o'nlik) boncuk [0]. Center. Y - (o'nlik) (boncuk [0]. Radius); } Properties. Settings. Default.size = 15; Xususiyatlar. Sozlamalar. Default.height = 15; } boshqa {

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

agar (doiralar. Uzunlik> 1) {Ro'yxat xs = doiralar. ni tanlang (c => c. Center. X). ToList (); xs. Sort (); Ro'yxat ys = doiralar. Ni tanlang (c => c. Center. Y). ToList (); ys. Sort ();

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

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

agar (medianX> tasvir. Kenglik - 15)

medianX = tasvir. Kenglik - 15; agar (medianY> tasvir. Balandlik - 15) medyanY = tasvir. Yuqori - 15;

tasvir. Doira (medianX, medyanY, 100, yangi Skalyar (0, 0, 150), 3);

agar (aniqlansa) {

Properties. Settings. Default.x = medianX - 7; Xususiyatlar. Sozlamalar. Default.y = medianY - 7; Properties. Settings. Default.size = 15; Xususiyatlar. Sozlamalar. 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 = yangi Mat (rasm, r);

Skalar avgColor = Cv2. Mean (beadSample); detectColor = Color. FromArgb ((int) avgColor [2], (int) avgColor [1], (int) avgColor [0]);

tasvir. To'g'ri to'rtburchak (r, yangi Skalyar (0, 150, 0));

window. ShowImage (rasm);

Cv2. WaitKey (1); videoRunning = to'g'ri; }

videoRunning = noto'g'ri;

} }

shaxsiy bo'sh kameraStartBtn_Click (ob'ekt yuboruvchi, EventArgs e) {

agar (cameraStartBtn. Text == "boshlash") {

cvThread = yangi mavzu (yangi ThreadStart (cvThreadFunction)); runVideo = to'g'ri; cvThread. Start (); cameraStartBtn. Text = "to'xtatish"; while (! videoRunning) Thread. Sleep (100);

updateColorTimer. Start ();

} boshqa {

runVideo = noto'g'ri; cvThread. Join (); cameraStartBtn. Text = "boshlash"; }}

Rang

Endi biz boncukning rangini aniqlay olamiz va qaysi rangga qarab uni qaysi idishga tashlashni hal qila olamiz.

Bu qadam ranglarni taqqoslashga asoslangan. Biz yolg'on musbatlikni cheklash uchun ranglarni ajrata olmoqchimiz, lekin soxta negativlarni chegaralash uchun etarli chegaraga ruxsat berishni xohlaymiz. Ranglarni solishtirish aslida hayratlanarli darajada murakkab, chunki kompyuterlarning ranglarni RGB sifatida saqlashi va odamlarning ranglarni idrok etishlari chiziqli bog'liq emas. Vaziyatni yomonlashtirish uchun, ko'rib turgan yorug'lik rangini ham hisobga olish kerak.

Rang farqini hisoblash uchun murakkab algoritm mavjud. Biz CIE2000 -dan foydalanamiz, bu raqam 1 ga yaqin bo'lsa, 2 ta rang odam uchun farq qilmaydi. Biz ColorMine C# kutubxonasidan ushbu murakkab hisob -kitoblarni bajarish uchun foydalanmoqdamiz. DeltaE -ning 5 -qiymati noto'g'ri ijobiy va noto'g'ri salbiy o'rtasida yaxshi murosaga kelishi aniqlandi.

Konteynerlardan ko'ra ko'proq ranglar ko'p bo'lganligi sababli, oxirgi joy yig'iladigan quti sifatida saqlanadi. Men, odatda, mashinani ikkinchi uzatishda ishlash uchun bir chetga suraman.

Ro'yxat

ranglar = yangi ro'yxat (); ro'yxat colorPanels = yangi ro'yxat (); Ranglar ro'yxatiTxts = new List (); ColorCnts ro'yxati = yangi ro'yxat ();

const int numColorSpots = 18;

const int unknownColorIndex = 18; int findColorPosition (rang c) {

Console. WriteLine ("Rang topilmoqda …");

var cRGB = yangi Rgb ();

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

int bestMatch = -1;

er -xotin matchDelta = 100;

uchun (int i = 0; i <ranglar. Count; i ++) {

var RGB = yangi Rgb ();

RGB. R = ranglar . R; RGB. G = ranglar . G; RGB. B = ranglar . B;

er -xotin delta = cRGB. Compare (RGB, yangi CieDe2000Comparison ());

// juft delta = deltaE (c, ranglar ); Console. WriteLine ("DeltaE (" + i. ToString () + "):" + delta. ToString ()); agar (delta <matchDelta) {matchDelta = delta; bestMatch = i; }}

if (matchDelta <5) {Console. WriteLine ("Topildi! (Posn:" + bestMatch + "Delta:" + matchDelta + ")"); bestMatch -ga qaytish; }

if (colors. Count <numColorSpots) {Console. WriteLine ("Yangi rang!"); ranglar Qo'shish (c); this. BeginInvoke (yangi Action (setBackColor), yangi ob'ekt {colors. Count - 1}); writeOutColors (); qaytish (ranglar soni - 1); } else {Console. WriteLine ("Noma'lum rang!"); unknownColorIndex -ni qaytarish; }}

Mantiqni saralash

Saralash funktsiyasi boncuklarni saralash uchun barcha qismlarni birlashtiradi. Bu funksiya ajratilgan mavzuda ishlaydi; yuqori plastinkani siljitish, boncuk rangini aniqlash, axlat qutisiga joylashtirish, ustki plastinkaning tekis holatda turishiga ishonch hosil qilish, boncuklarni sanash va h.k. Qopqoq qutisi to'lganida u ham ishlamay qoladi - Aks holda, biz to'lib toshgan munchoqlar bilan tugaymiz.

Boolean runtest = false; yaroqsiz rang testi () {

agar (! yuqori. g'azablangan)

top. Engaged = rost;

agar (! pastki. g'azablangan)

pastki. Engaged = rost;

while (runtest) {

nextMagnet (haqiqiy);

Uyqu (100); harakat qilib ko'ring {if (magSensor. SensorValue <(magSensorMax - 4)) alignMotor (); } ushlash {alignMotor (); }

nextCamera (haqiqiy);

aniqlash = rost;

while (detectCnt <5) Thread. Sleep (25); Console. WriteLine ("Detect Count:" + detectCnt); aniqlash = noto'g'ri;

Rang c = aniqlanganColor;

this. BeginInvoke (yangi Action (setColorDet), yangi ob'ekt {c}); int i = findColorPosition (c);

SetBottomPosition (i, rost);

nextHole (haqiqiy); colorCnts ++; this. BeginInvoke (yangi Action (setColorTxt), yangi ob'ekt {i}); Uyqu (250);

agar (colorCnts [unknownColorIndex]> 500) {

top. Engaged = false; pastki. Engaged = false; runtest = noto'g'ri; this. BeginInvoke (yangi Action (setGoGreen), null); qaytish; }}}

shaxsiy bo'sh rang colourTestBtn_Click (ob'ekt yuboruvchi, EventArgs e) {

if (colourTestThread == null ||! colourTestThread. IsAlive) {colourTestThread = yangi mavzu (yangi ThreadStart (colourTest))); runtest = rost; colourTestThread. Start (); colourTestBtn. Text = "To'xtatish"; colourTestBtn. BackColor = Color. Red; } boshqa {runtest = false; colourTestBtn. Text = "GO"; colourTestBtn. BackColor = Color. Green; }}

Bu vaqtda bizda ishchi dastur mavjud. Maqolada ba'zi kodlar qoldirilgan, shuning uchun uni ishga tushirish uchun manbaga qarang.

Optika tanlovi
Optika tanlovi

Optika tanlovining ikkinchi sovrini

Tavsiya: