Mündəricat:
- Addım 1: Materiallarınızı toplayın
- Addım 2: MATLAB üçün Roomba alət qutularını yükləyin
- Addım 3: Roomba -ya qoşulun
- Addım 4: Roombanı necə idarə etmək istədiyinizi seçin
- Addım 5: Roombanı sürün
Video: Otağınızı Mars Roverinə çevirmək: 5 addım
2024 Müəllif: John Day | [email protected]. Son dəyişdirildi: 2024-01-30 07:43
Addım 1: Materiallarınızı toplayın
Bu layihəni başa çatdırmaq üçün aşağıdakı materialları toplamalısınız:
1 otaqlı robot
1 Raspberry Pi Kit
1 Video Kamera
MATLAB -a giriş
Addım 2: MATLAB üçün Roomba alət qutularını yükləyin
Bu layihəni tamamlamaq üçün lazım olan alət qutularını quraşdırmaq üçün aşağıdakı kodu işlədin.
roombaInstall funksiyası
clc;
quraşdırılacaq faylların % siyahısı
fayllar = {'roomba.m', 'roombaSim.m', 'roombaSimGUI.m', 'roombaSimGUI.fig'};
quraşdırılacaq % yer
variantlar = weboptions ('CertificateFilename', ''); sertifikat tələblərinə məhəl qoymamağı söyləyir
server = 'https://ef.engr.utk.edu/ef230/projects/roomba-f2016/install/';
dlgTitle = 'Roomba Quraşdır/Yeniləyin';
% keçirmək məqsədi və təsdiq almaq
istək = {
'Bu proqram bu EF 230 Roomba fayllarını yükləyəcək:'
''
strjoin (fayllar, '')
''
'bu qovluğa:'
''
cd
''
'Davam etmək istəyirsən? '
};
bip;
yn = questdlg (tez,…
dlgTitle,…
'Bəli', 'Xeyr', 'Bəli');
if ~ strcmp (yn, 'Yes'), return; bitmək
% mövcud faylların siyahısını alır
Mevcut_files = fayllar (cellfun (@exist, files)> 0);
if ~ isempty (mövcud_fayllar)
Onları dəyişdirməyin həqiqətən yaxşı olduğuna əmin olun
prompt = {'Bu faylları dəyişdirirsiniz:'
''
strjoin (mövcud_files, '')
''
'Əvəz etmək yaxşıdır?'
};
bip;
yn = questdlg (tez,…
dlgTitle,…
'Bəli', 'Xeyr', 'Bəli');
if ~ strcmp (yn, 'Yes'), return; bitmək
bitmək
% faylları yükləyin
cnt = 0;
i = 1 üçün: uzunluq (fayllar)
f = fayllar {i};
disp (['Yüklənir' f]);
cəhd edin
url = [server f];
websave (f, url, seçimlər); % təhlükəsizlik səhvlərinin qarşısını almaq üçün seçimlər əlavə etdi
cnt = cnt + 1;
tutmaq
disp (['Yükləmə xətası' f]);
kukla = [f '.html'];
varsa (kukla, 'fayl') == 2
sil (kukla)
bitmək
bitmək
bitmək
əgər cnt == uzunluğu (fayllar)
msg = 'Quraşdırma Uğurlu';
waitfor (msgbox (msg, dlgTitle));
başqa
msg = 'Quraşdırma xətası - ətraflı məlumat üçün komanda pəncərəsinə baxın';
waitfor (səhv (msg, dlgTitle));
bitmək
son %roombaInstall
Addım 3: Roomba -ya qoşulun
İndi WiFi istifadə edərək Roombanıza qoşulmağın vaxtıdır. Roombanı yandırmaq və ya sıfırlamaq üçün 2 barmaqdan istifadə edərək Dock və Spot düymələrinə eyni vaxtda basın. Sonra robotunuza qoşulmaq üçün MATLAB -ın komanda pəncərəsində r = roomba kodunu (Roombanızın# nömrəsi) işlədin. Bu əmri yerinə yetirdikdən sonra Roombanız işə hazır olmalıdır.
Addım 4: Roombanı necə idarə etmək istədiyinizi seçin
Roomba'nızı idarə etməyin iki yolu var: muxtar və ya nəzarətçi olaraq bir smartfon istifadə etmək.
Roombanı avtonom idarə etməyi seçsəniz, üç quraşdırılmış sensordan istifadə etməlisiniz: uçurum, qabar sensoru və işıq sensoru.
Bir smartfondan istifadə etmək üçün əvvəlcə aşağıdakı addımları yerinə yetirərək smartfonunuzu kompüterinizə bağlamalısınız.
QEYD: Düzgün qoşulmaq üçün kompüterinizin və smartfonunuzun eyni WiFi şəbəkəsində olması lazımdır!
1. Cihazınızdakı tətbiq mağazasından MATLAB tətbiqini yükləyin.
2. Komanda pəncərənizə "Connector on" yazın və hər iki cihaza daxil edilməli olan bir parol təyin edin.
3. Bunu etdikdən sonra MATLAB sizə kompüterlərinizin IP ünvanını verəcək. Smartfonunuzdakı MATLAB tətbiqindəki parametrlər səhifəsinə daxil olmalısınız və əvvəllər daxil etdiyiniz IP ünvanını və şifrənizi istifadə edərək kompüter əlavə etməlisiniz.
4. Kompüterinizin komanda pəncərəsinə m = mobiledev kodunu yazın və bu, smartfonunuzu Roomba üçün nəzarətçi kimi işə salmalıdır.
5. Kompüteriniz və smartfonunuz artıq işə hazır olmalıdır.
Addım 5: Roombanı sürün
Mars Rover -inizi yaratmaq üçün bütün lazımi vasitələrə sahib olduğunuz üçün öz kodunuzu hazırlamağa hazırsınız. Aşağıda həm avtonom idarəetmə, həm də smartfonla idarə olunan idarəetmə üçün bir nümunə kodu əlavə etdik.
Avtonom Sürücülük
Explore_modified funksiyası (r)
%giriş arqumentləri: 1 roomba obyekti, r
%çıxış arqumentləri: heç biri
%təsviri:
%funksiyası muxtar olmaq üçün sonsuz müddət istifadə edir
bot ətrafında kəşfiyyat.
%
funciton da Roomba üçün nə etmək üçün təlimat verir
Aşağıdakı hallar: Təkər (lər) yerlə təmasını itirir, bir
%obyekti botun qarşısında və ya hər iki tərəfində aşkar edilir və a
ani düşmə botun qarşısında və ya hər iki tərəfində aşkar edilir.
%
tipik təlimatlara maksimuma çatdırmaq üçün nəzərdə tutulmuş hərəkət əmrləri daxildir
kəşfiyyat və ya aşkar təhlükə və ünsiyyət əmrləri qarşısını almaq
botların kəşfləri (şəkillər), mövqe (qrafik) ilə bağlı %məlumat, %və dövlət (qapalı xəbərdarlıq) istifadəçi ilə matlab və/və ya e -poçt vasitəsilə. Bir neçə
zövq üçün səs əmrləri əlavə olunur.
%e -poçt imkanlarını qurmaq
poçt = '[email protected]';
parol = 'EF230Roomba';
setpref ('İnternet', 'SMTP_Server', 'smtp.gmail.com');
setpref ('İnternet', 'E_mail', poçt);
setpref ('İnternet', 'SMTP_Username', poçt);
setpref ('İnternet', 'SMTP_Password', parol);
rekvizit = java.lang. System.getProperties;
props.setProperty ('mail.smtp.starttls.enable', 'true');
props.setProperty ('mail.smtp.auth', 'doğru');
props.setProperty ('mail.smtp.socketFactory.class', 'javax.net.ssl. SSLSocketFactory');
props.setProperty ('mail.smtp.socketFactory.port', '465');
% r = roomba (19)
r.beep ('G2 ^^, G2 ^^, G2 ^^, G2 ^^, A2 ^^, A2 ^^, G1 ^^, E1 ^^, C2 ^^, C2 ^^, C1 ^^, C1 ^^, D1 ^^, C1 ^^, D2 ^^, E4 ^^, G2 ^^, G2 ^^, G2 ^^, G2 ^^, A2 ^^, A2 ^^, G1 ^^, E1 ^^, C2 ^^, C2 ^^, C2 ^^, E1 ^^, E1 ^^, E1 ^^, D1 ^^, C4 ^^ ');
v =.1;
əks_datum = 2700; uçurum sensörlərinin istinad dəyərini təyin edin
lightBumper_datum = 200; işığın tampon sensorlar istinad dəyərini təyin edin
pos = [0, 0]; Başlanğıc nöqtəsi ilə mövqe saxlama üçün %dəyişən
bucaq = 0; istinad açısını təyin edən %
netangle = 0; %xalis bucaq yerdəyişməsi
i = 2; mövqe saxlama dəyişəninə satır əlavə etmək üçün %iterator
dist = 0;
r.setDriveVelocity (v, v); Roomba -nın irəli getməsinə başlayın
doğru olarkən
Cliff = r.getCliffSensors;
Bump = r.getBampers;
İşıq = r.getLightBampers;
RandAngle = randi ([20, 60], 1); %20 ilə 60 dərəcə arasında 1 təsadüfi bucaq yaradır. Botun bir döngədə ilişib qalmaması üçün istifadə olunur
Bir və ya daha çox təkərin yerlə əlaqəsi kəsilərsə nə etməli:
hərəkəti dayandırın, ətrafın şəkli olan bir xəbərdarlıq e -poçtu göndərin, və davam etmək və ya kömək gözləmək istifadəçi soruşun
əgər Bump.rightWheelDrop == 1 || Bump.leftWheelDrop == 1
r.stop
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
r.beep ('F#1 ^^, C1 ^^, F#1 ^^, C1 ^^, F#1 ^^, C1 ^^, F#1 ^^, C1 ^^, F#1 ^^, C1 ^^, F#1 ^^, C1 ^^, F#1 ^^, C1 ^^, F#1 ^^, C1 ^^ ')
img = r.getImage;
imwrite (img, 'stuck.png');
%--------------------------
imfile = 'stuck.png';
mövqe = qənaət nöqtələri (pos);
%---------------------------
sendmail (poçt, 'YARDIM!', 'Mən uçurumda qalmışam!', {imfile, mövqe})
list = {'Davam et', 'Dur'};
idx = menyu ('Nə etməliyəm?', siyahı);
idx == 2 olarsa
fasilə
bitmək
Botun qarşısında bir obyekt aşkar edilərsə nə etməli:
dayandırmaq, geri çəkilmək, şəkil çəkmək, istifadəçini kəşf edin
E -poçt vasitəsilə, 90 dərəcə dönün və araşdırmağa davam edin
elseif Light.leftCenter> lightBumper_datum || Light.rightCenter> lightBumper_datum || Bump.front == 1
r.stop;
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
r.moveDistance (-. 125);
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
r.beep ('A1^, A1^, A4^, A2^, G2^, G2^, G4^, Bb2^, Bb2^, Bb3.5^, G1^, A8^')
img = r.getImage;
imwrite (img, 'FrontBump.png')
%--------------------------
imfile = 'FrontBump.png';
mövqe = qənaət nöqtələri (pos);
%---------------------------
sendmail (poçt, 'Xəbərdarlıq!', 'Bir şey tapdım!', {imfile, mövqe})
bucaq = 90;
netangle = netangle+bucaq;
r.turnAngle (bucaq);
r.setDriveVelocity (v, v);
Botun solunda obyekt aşkarlanarsa nə etməli:
dayandırmaq, obyektə doğru dönmək, geri çəkmək, şəkil çəkmək, xəbərdarlıq etmək
E -poçt vasitəsilə kəşf istifadəçisi, 90 dərəcə dönün və araşdırmağa davam edin
elseif Light.leftFront> lightBumper_datum || Light.left> lightBumper_datum || Bump.left == 1
r.stop;
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
bucaq = 30;
netangle = netangle+bucaq;
r.turnAngle (bucaq);
r.moveDistance (-. 125);
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
r.beep ('A4^, A4^, G1^, E1^, C3.5^, C2 ^^, C1^, C1^, C2^, D2^, D2^, E8^')
img = r.getImage;
imwrite (img, 'LeftBump.png')
%--------------------------
imfile = 'LeftBump.png';
mövqe = qənaət nöqtələri (pos);
%---------------------------
sendmail (poçt, 'Xəbərdarlıq!', 'Bir şey tapdım!', {imfile, mövqe})
bucaq = -90;
netangle = netangle+bucaq;
r.turnAngle (bucaq);
r.setDriveVelocity (v, v);
Obyekt botun sağında aşkar edilərsə nə etməli:
dayandırmaq, obyektə doğru dönmək, geri çəkmək, şəkil çəkmək, xəbərdarlıq etmək
E -poçt vasitəsilə kəşf istifadəçisi, 90 dərəcə dönün və araşdırmağa davam edin
elseif Light.rightFront> lightBumper_datum || Light.right> lightBumper_datum || Bump.right == 1
r.stop;
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
bucaq = -30;
netangle = netangle+bucaq;
r.turnAngle (bucaq);
r.moveDistance (-. 125);
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
fasilə (1.5);
r.beep ('C1^, C1^, C2^, D2^, D2^, C8^')
img = r.getImage;
imwrite (img, 'RightBump.png')
%--------------------------
imfile = 'RightBump.png';
mövqe = qənaət nöqtələri (pos);
%---------------------------
sendmail (poçt, 'Xəbərdarlıq!', 'Bir şey tapdım!', {imfile, mövqe});
bucaq = 90;
netangle = netangle+bucaq;
r.turnAngle (bucaq);
r.setDriveVelocity (v, v);
Botun solunda uçurum aşkarlanarsa nə etməli:
dayandırın, geriyə doğru hərəkət edin, sağa dönün, araşdırmağa davam edin
elseif Cliff.left <reflect_datum || Cliff.leftFront <reflect_datum
r.stop;
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
r.moveDistance (-. 125);
dist = r.getDistance;
pos (i, 1) = pos (i-1, 1) + dist * sind (netangle); %x koordinatını əldə edin
pos (i, 2) = pos (i-1, 2) + dist * cosd (netangle); %koordinat əldə edin
i = i+1;
bucaq = -RandAngle;
netangle = netangle+bucaq;
r.turnAngle (bucaq);
r.setDriveVelocity (v, v);
Botun sağında uçurum aşkarlanarsa nə etməli:
dayandırın, geriyə doğru hərəkət edin, sola dönün, araşdırmağa davam edin
elseif Cliff.right <reflect_datum || Cliff.rightFront <reflect_datum
r.stop;
dist = r.getDistance;
pos (i, 1) = dist * sind (bucaq); %x koordinatını əldə edin
pos (i, 2) = dist * cosd (bucaq); %koordinat əldə edin
i = i+1;
r.moveDistance (-. 125);
bucaq = RandAngle;
netangle = netangle+bucaq;
r.turnAngle (bucaq);
r.setDriveVelocity (v, v);
bitmək
bitmək
Smartfon Nəzarətçisi
Seçimlər = {'Muxtar', 'Manuel Nəzarət'}
Prompt = menyu ('Roveri necə idarə etmək istərdiniz?', Seçimlər)
m = mobil telefon
r = otaq (19)
İstem varsa == 1
Tədqiqatçı)
başqa
doğru olarkən
fasilə (.5)
Telefon Məlumatları = m. Orientasiya;
Azi = Telefon Məlumatları (1);
Pitch = Telefon Məlumatları (2);
Yan = Telefon Məlumatları (3);
əgər Yan> 130 || Telefonun üzü aşağı döndərildikdə <-130 %, otaqdakı işi dayandırın və döngədən çıxın
r.stop
r.bip ('C, C, C, C')
fasilə
elseif Side> 25 && Side <40 %, telefon 25 ilə 40 dərəcə arasında yan tərəfə çevrilirsə 5 dərəcə sola dönün
r.turnAngle (-5);
elseif Yan> 40 %, telefon 40 dərəcədən yuxarı yana çevrilirsə 45 dərəcə sola dönün
r.turnAngle (-45)
elseif Yan -40 %, telefon -25 ilə -40 dərəcə arasında yan tərəfə çevrilirsə 5 dərəcə sağa dönün
r.turnAngle (5);
elseif Yan <-40 %, telefon -40 dərəcədən aşağıya dönərsə 45 dərəcə sola dönər
r.turnAngle (45)
bitmək
Telefon verticle yaxın keçirilir varsa, bir şəkil almaq və süjet
əgər Pitch <-60 && image <= 9
r. səslənir
img = r.getImage;
alt sahə (3, 3, şəkil)
imshow (img)
bitmək
ön və arxa oriyentasiyasına əsaslanaraq irəli və geri hərəkət
əgər Pitch> 15 && Pitch <35 %, əgər 15 ilə 35 dərəcə arasındakı meydança qısa məsafəyə doğru irəliləsə
hərəkət etməzdən əvvəl yüngül tampon məlumatları əldə edir
litBump = r.getLightBumpers;
əgər litBump.leftFront> 500 || litBump.leftCenter> 500 || litBump.rightCenter> 500 || litBump.rightFront> 500 %bir şey roomba'nın önündədirsə və irəli hərəkət edərsə vuracaq səs -küy və mesaj göstərin
r.beep ('C ^^, F#^, C ^^, F#^')
başqa %hərəkət
r.moveDistance (.03);
Hərəkət sonra bamper data alın
Bump = r.getBampers;
əgər Bump.right == 1 || Bump.left == 1 || Bump.front == 1
r.bip ('A, C, E')
r.moveDistance (-. 01)
bitmək
uçurum sensoru məlumatlarını əldə edir
Cliff = r.getCliffSensors;
əgər Cliff.le> 1500 || Cliff.leftFront> 1500 || Cliff.rightFront> 1500 || Cliff.right> 1500 %bir şey uçurum sensörünü tetiklerse, ona lava və ehtiyat olaraq baxın
r.beep ('C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C')
r.moveDistance (-. 031)
bitmək
bitmək
elseif Pitch> 35 %, əgər meydança 35 dərəcə daha uzun məsafəyə irəliləsə
hərəkət etməzdən əvvəl yüngül tampon məlumatları əldə edir
litBump = r.getLightBumpers;
əgər litBump.leftFront> 15 || litBump.leftCenter> 15 || litBump.rightCenter> 15 || litBump.rightFront> 15 %, bir şey otaq başının qarşısında olarsa və irəli hərəkət edərsə vurarsa, səs -küy yaradın və mesaj göstərin
r.beep ('C ^^, F#^, C ^^, F#^')
başqa %hərəkət
r.moveDistance (.3)
Hərəkət sonra bamper data alın
Bump = r.getBampers;
əgər Bump.right == 1 || Bump.left == 1 || Bump.front == 1 %Bir şey vurursan səs -küy sal, mesaj göstər və yedəklə
r.bip ('A, C, E')
r.moveDistance (-. 01)
bitmək
hərəkət etdikdən sonra uçurum sensoru məlumatlarını əldə edir
Cliff = r.getCliffSensors;
əgər Cliff.le> 1500 || Cliff.leftFront> 1500 || Cliff.rightFront> 1500 || Cliff.right> 1500 %bir şey uçurum sensörünü tetiklerse, ona lava və ehtiyat olaraq baxın
r.beep ('C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C')
r.moveDistance (-. 31)
bitmək
bitmək
elseif Pitch -35 %-15 ilə -35 dərəcə arasındakı addım qısa məsafəyə geri hərəkət edərsə
r.moveDistance (-. 03);
hərəkət etdikdən sonra uçurum sensoru məlumatlarını əldə edir
Cliff = r.getCliffSensors;
əgər Cliff.le> 1500 || Cliff.leftFront> 1500 || Cliff.rightFront> 1500 || Cliff.right> 1500 %bir şey uçurum sensörünü tetiklerse, ona lava və ehtiyat olaraq baxın
r.beep ('C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C')
r.moveDistance (.04)
bitmək
elseif Pitch -60 ilə -35 və -60 dərəcə arasındakı meydança daha uzun məsafəyə geri hərəkət edərsə
r.moveDistance (-. 3)
hərəkət etdikdən sonra uçurum sensoru məlumatlarını əldə edir
Cliff = r.getCliffSensors;
əgər Cliff.le> 1500 || Cliff.leftFront> 1500 || Cliff.rightFront> 1500 || Cliff.right> 1500 %bir şey uçurum sensörünü tetiklerse, ona lava və ehtiyat olaraq baxın
r.beep ('C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C, C ^^, C')
r.moveDistance (.31)
bitmək
bitmək
bitmək
bitmək
Tövsiyə:
230V AC ampulünü USB gücünə çevirmək: 6 addım (şəkillərlə)
230V AC ampulünü USB Gücünə çevirmək !: eBay-də titrəyən və içərisində incə bir animasiya olan bu səliqəli alov effektli ampullərə rast gəldim. Adətən 85-265V AC şəbəkə girişi ilə işləyirlər, ancaq portativ tətbiqlər üçün. saxta yanan məşəl və ya fənər bu ideal deyil
Bluetooth qulaqlıqlarımı Bluetooth dinamiklərinə çevirmək: 5 addım
Bluetooth Qulaqlığımı Bluetooth Dinamiklərə Dönüştürmək: Qulaqlığım artıq öz-özünə işləmir, yalnız mikro-USB konnektorunu şarj edərkən bağlayıram, batareya artıq sönmüş və dinamiklərdən biri işləmir. Ancaq Bluetooth hələ də problemsiz işləyir, bu gün göstərəcəyəm
Arduino ilə otağınızı necə avtomatlaşdırmaq olar? 1 -ci hissə: 5 addım
Arduino ilə otağınızı necə avtomatlaşdırmaq olar? 1 -ci hissə: Həmişə otağımı uzaqdan idarə etmək istəyirdim, buna görə də bunu etməyə imkan verən bir sistem yaratmağa qərar verdim. Necə öyrənmək istəyirsən? sonra sizi aşağıdakı addımları izləməyə dəvət edirəm
Siqnal: Otağınızı tərk etməyinizi xatırlatmaq: 5 addım
Siqnal: Otağınızı tərk etməyinizi xatırlatmaq: Bu sizi otaqdan çıxmağa məcbur etmək üçün hazırlanmış bir siqnaldır. Müəyyən edilmiş vaxt çatdıqda, cihazdakı dinamik sönəcək və işığı söndürənə qədər səs siqnalı verməyə davam edəcək
Google köməkçisi və Arduino ilə otağınızı necə avtomatlaşdırmaq olar ?: 7 addım
Otağınızı Google Assistant və Arduino ilə necə avtomatlaşdırmaq olar ?: Salam Təlimatlı cəmiyyət, burada başqa bir avtomatlaşdırma layihəsi, xüsusən də Google Assistant, Arduino və bəzi veb platformaları olan səsli idarəetmə sistemiyəm. cihazların səslə idarə olunmasını dəstəkləyin, çünki