Bu projede Factory IO’daki otomasyon projelerinden biri olan paletleme istasyonunun elektrik bağlantı şemasını EPLAN üzerinde tasarladım. Sistemin genel görünümü aşağıdaki gibidir.

Projeyi ise aşağıdaki gibi çizdim.





























Bu projede Factory IO’daki otomasyon projelerinden biri olan paletleme istasyonunun elektrik bağlantı şemasını EPLAN üzerinde tasarladım. Sistemin genel görünümü aşağıdaki gibidir.

Projeyi ise aşağıdaki gibi çizdim.





























Bu projede Factory IO’daki otomasyon projelerinden biri olan renk ayırma istasyonunun elektrik bağlantı şemasını EPLAN üzerinde tasarladım. Sistemin genel görünümü ve panonun görünümü aşağıdaki gibidir.


Projeyi ise aşağıdaki gibi çizdim.


















Bu uygulamada birden çok istasyonu aynı hat üzerinde tek bir PLC üzerinden kontrol ederek programı yazdım. Daha sonra bu istasyonlar için bir operatör paneli tasarladım. Sistem 3 ana bölümden oluşuyor. İlk istasyonda hatalı parçalar ayrıştırılıyor ve birleştiriliyor. İkinci istasyonda paletleniyor. Üçüncü istasyonda ise depolanıyor. Sistemin çalışma videosu aşağıdadır.

İlk olarak ayrıştırma istasyonunun programını yazdım.



Bu yazdığım FB’yi daha sonra OB üzerinde çağırdım ve giriş/çıkışları tanımladım.

Daha sonra Pick and Place kısmının programını yazdım. Bu fonksiyonu SCL ile yazdım.
IF #Yeni_Palet = TRUE AND #Palet_Sensor = TRUE THEN
#Roller_Stop := 0;
#Konveyor_Giris := 1;
#Giris_Adımı := 1;
#Yeni_Palet := 0;
END_IF;
IF #Giris_Adımı=TRUE AND #Palet_Sensor = FALSE THEN
#Konveyor_Giris := 0;
#Giris_Adımı := 0;
END_IF;
(*
Palet Geldikten Sonra Program Akışı Başlıyor
*)
IF #Palet_Sensor=FALSE AND #Hat1_Hazir=TRUE AND #Hat2_Hazir=TRUE THEN
#Adım1 := TRUE;
"Ayristirma_Veri".Hat1_Hazir := 0;
"Ayristirma_Veri".Hat2_Hazir := 0;
END_IF;
IF #Adım1 = TRUE THEN
#Setpoint_X:= "Pick_and_Place_Veri".Kapak_Alma_Ust.X;
#Setpoint_Y := "Pick_and_Place_Veri".Kapak_Alma_Ust.Y;
#Setpoint_Z := "Pick_and_Place_Veri".Kapak_Alma_Ust.Z;
#Adım1 := FALSE;
#Adım2 := 1;
END_IF;
IF #Adım2 = TRUE AND #Pozisyon_X = "Pick_and_Place_Veri".Kapak_Alma_Ust.X AND #Pozisyon_Y = "Pick_and_Place_Veri".Kapak_Alma_Ust.Y AND #Pozisyon_Z = "Pick_and_Place_Veri".Kapak_Alma_Ust.Z THEN
#Setpoint_X := "Pick_and_Place_Veri".Kapak_Alma.X;
#Setpoint_Y := "Pick_and_Place_Veri".Kapak_Alma.Y;
#Setpoint_Z := "Pick_and_Place_Veri".Kapak_Alma.Z;
#Adım2 := 0;
#Adım3 := 1;
END_IF;
IF #Adım3 = TRUE AND #Pozisyon_X = "Pick_and_Place_Veri".Kapak_Alma.X AND #Pozisyon_Y = "Pick_and_Place_Veri".Kapak_Alma.Y AND #Pozisyon_Z = "Pick_and_Place_Veri".Kapak_Alma.Z AND #Tutma_Sensor=TRUE THEN
#Tutma := 1;
#Adım3 := 0;
#Adım4 := 1;
#Setpoint_X := "Pick_and_Place_Veri".Kapak_Alma_Ust.X;
#Setpoint_Y := "Pick_and_Place_Veri".Kapak_Alma_Ust.Y;
#Setpoint_Z := "Pick_and_Place_Veri".Kapak_Alma_Ust.Z;
END_IF;
IF #Adım4 = TRUE AND #Pozisyon_X = "Pick_and_Place_Veri".Kapak_Alma_Ust.X AND #Pozisyon_Y = "Pick_and_Place_Veri".Kapak_Alma_Ust.Y AND #Pozisyon_Z = "Pick_and_Place_Veri".Kapak_Alma_Ust.Z THEN
#Setpoint_X := "Pick_and_Place_Veri".Kapak_Bırakma.X;
#Setpoint_Y := "Pick_and_Place_Veri".Kapak_Bırakma.Y;
#Setpoint_Z := "Pick_and_Place_Veri".Kapak_Bırakma.Z;
#Adım4 := 0;
#Adım5 := 1;
#Yeni_Parca := 1;
END_IF;
IF #Adım5 = TRUE AND #Pozisyon_X = "Pick_and_Place_Veri".Kapak_Bırakma.X AND #Pozisyon_Y = "Pick_and_Place_Veri".Kapak_Bırakma.Y AND #Pozisyon_Z = "Pick_and_Place_Veri".Kapak_Bırakma.Z THEN
#Tutma := 0;
#Setpoint_X := "Pick_and_Place_Veri".Parca_Alma.X;
#Setpoint_Y := "Pick_and_Place_Veri".Parca_Alma.Y;
#Setpoint_Z := "Pick_and_Place_Veri".Parca_Alma.Z;
#Adım5 := 0;
#Adım6 := 1;
END_IF;
IF #Adım6 = TRUE AND #Pozisyon_X = "Pick_and_Place_Veri".Parca_Alma.X AND #Pozisyon_Y = "Pick_and_Place_Veri".Parca_Alma.Y AND #Pozisyon_Z = "Pick_and_Place_Veri".Parca_Alma.Z THEN
#Tutma := 1;
#Setpoint_X := "Pick_and_Place_Veri".Parca_Alma_Ust.X;
#Setpoint_Y := "Pick_and_Place_Veri".Parca_Alma_Ust.Y;
#Setpoint_Z := 0;
#Adım6 := 0;
#Adım6_AraAdım := 1;
END_IF;
IF #Adım6_AraAdım=TRUE AND #Pozisyon_X = "Pick_and_Place_Veri".Parca_Alma_Ust.X AND #Pozisyon_Y = "Pick_and_Place_Veri".Parca_Alma_Ust.Y AND #Pozisyon_Z = 0 THEN
#Setpoint_X := "Pick_and_Place_Veri".Parca_Bırakma.X;
#Setpoint_Y := "Pick_and_Place_Veri".Parca_Bırakma.Y;
#Adım6_AraAdım := 0;
#Adım7 := 1;
#Yeni_Parca := 0;
END_IF;
IF #Adım7 = TRUE AND #Pozisyon_X = "Pick_and_Place_Veri".Parca_Bırakma.X AND #Pozisyon_Y = "Pick_and_Place_Veri".Parca_Bırakma.Y AND #Pozisyon_Z = 0 THEN
IF "Pick_and_Place_Veri".Paletteki_Parca_Sayisi = 0 OR "Pick_and_Place_Veri".Paletteki_Parca_Sayisi = 2 OR "Pick_and_Place_Veri".Paletteki_Parca_Sayisi = 4 THEN
#Setpoint_X := "Pick_and_Place_Veri".Parca_Bırakma.X;
#Setpoint_Y := "Pick_and_Place_Veri".Parca_Bırakma.Y;
#Setpoint_Z := "Pick_and_Place_Veri".Parca_Bırakma.Z;
ELSIF "Pick_and_Place_Veri".Paletteki_Parca_Sayisi = 1 OR "Pick_and_Place_Veri".Paletteki_Parca_Sayisi = 3 OR "Pick_and_Place_Veri".Paletteki_Parca_Sayisi = 5 THEN
#Setpoint_X := "Pick_and_Place_Veri".Parca_Bırakma.X + 1.9;
#Setpoint_Y := "Pick_and_Place_Veri".Parca_Bırakma.Y;
#Setpoint_Z := "Pick_and_Place_Veri".Parca_Bırakma.Z;
END_IF;
#Adım7 := 0;
#Adım8 := 1;
END_IF;
IF #Adım8 = TRUE AND (#Pozisyon_X = "Pick_and_Place_Veri".Parca_Bırakma.X OR #Pozisyon_X = "Pick_and_Place_Veri".Parca_Bırakma.X+1.9) AND #Pozisyon_Y = "Pick_and_Place_Veri".Parca_Bırakma.Y AND #Pozisyon_Z = "Pick_and_Place_Veri".Parca_Bırakma.Z THEN
#Tutma := 0;
"Pick_and_Place_Veri".Paletteki_Parca_Sayisi += 1;
#Adım8 := 0;
END_IF;
(*
Palet Dolduktan Sonra Depoya Yollama Adımları
*)
IF "Pick_and_Place_Veri".Paletteki_Parca_Sayisi = "Pick_and_Place_Veri".Olmasi_Gereken_Parca THEN
#Roller_Stop := 1;
#Konveyor_Giris := 1;
#Konveyor_Devam := 1;
#Konveyor_Palet := 1;
#Cıkıs_Adımı := 1;
"Pick_and_Place_Veri".Paletteki_Parca_Sayisi := 0;
END_IF;
IF #Cıkıs_Adımı = TRUE AND #Depo_Palet_Sensor = false THEN
#Roller_Stop := 0;
#Konveyor_Palet := 0;
#Konveyor_Giris := 0;
#Konveyor_Devam := 0;
#Cıkıs_Adımı := 0;
#Yeni_Palet := 1;
END_IF;
Daha sonra bu FB’yi de OB üzerinden çağırdım.

Son olarak depolama istasyonu için bir program yazdım.





Bu FB içinde kullandığım hücre seçim FC’si de aşağıdaki gibi
#X_setpoint := "Depolama_Hücreler_Veri".Hücre[#Sıra , #Sütun].X;
#Z_setpoint := "Depolama_Hücreler_Veri".Hücre[#Sıra, #Sütun].Z;
Daha sonra OB içinde bu fonksiyonu ekledim.

HMI içinde kullandığım animasyonlar için ve yuvarlamalar için de SCL ile ayrı bir FC yazdım.
"HMI_Animasyon_DB".PickandPlace_X := REAL_TO_INT("Pick_and_Place_Veri".Gercek_Pozisyon.X);
"HMI_Animasyon_DB".PickandPlace_Y := REAL_TO_INT("Pick_and_Place_Veri".Gercek_Pozisyon.Y);
"HMI_Animasyon_DB".PickandPlace_Z := REAL_TO_INT("Pick_and_Place_Veri".Gercek_Pozisyon.Z);
"HMI_Animasyon_DB".Depolama_X := REAL_TO_INT("Depolama_Hücreler_Veri".Gercek_Pozisyon_X*10);
"HMI_Animasyon_DB".Depolama_Z := REAL_TO_INT("Depolama_Hücreler_Veri".Gercek_Pozisyon_Z*10);
"HMI_Animasyon_DB".Depolama_Dolu := "Depo_Palet_Sayisi".CV;
"HMI_Animasyon_DB".Depolama_Bos := (54 - "HMI_Animasyon_DB".Depolama_Dolu);
"Üretilen Parça" := "HMI_Animasyon_DB".Depolama_Dolu;
#X_aradeger := ("X_Poz_Bilgi" * 10);
#X_aradeger := ROUND(#X_aradeger);
"Pick_and_Place_Veri".Gercek_Pozisyon.X := #X_aradeger/10;
#Y_aradeger := ("Y_Poz_Bilgi" * 10);
#Y_aradeger := ROUND(#Y_aradeger);
"Pick_and_Place_Veri".Gercek_Pozisyon.Y := #Y_aradeger / 10;
#Z_aradeger := ("Z_Poz_Bilgi" * 10);
#Z_aradeger := ROUND(#Z_aradeger);
"Pick_and_Place_Veri".Gercek_Pozisyon.Z := #Z_aradeger / 10;
#Depo_X_aradeger := ("Asansor_X_Pozisyon" * 100);
#Depo_X_aradeger := ROUND(#Depo_X_aradeger);
"Depolama_Hücreler_Veri".Gercek_Pozisyon_X := #Depo_X_aradeger / 100;
#Depo_Z_aradeger := ("Asansor_Z_Pozisyon" * 100);
#Depo_Z_aradeger := ROUND(#Depo_Z_aradeger);
"Depolama_Hücreler_Veri".Gercek_Pozisyon_Z := #Depo_Z_aradeger / 100;
Programı yazarken kendi tanımladığım data tipleri de aşağıdaki gibi.

PLC programı bittikten sonra HMI tasarımını yaptım. HMI ekranların görüntüleri de aşağıdaki gibidir.
Bu uygulamada tank seviye kontrolü için TIA Portal içinde fonksiyon bloğu olarak bulunan PID_Compact fonksiyonunu kullandım. PID kontrolcü sayesinde tank setpoint değerinin ani değişimlerinde veya tankı boşaltan vananın ani değişimlerinde tank seviyesinin olabildiğince istenilen değerde kalmasını sağladım. PID sayesinde ani değişimlere çabuk ve daha yumuşak bir tepki veriliyor.
İlk olarak Factory I/O simülasyon programı içinde su tankı ve kontrol panosu ekleme işlemlerini yaptım. Kontrol panosuna gerekli buton ve göstergeleri ekledim.

Daha sonra PLC’nin giriş ve çıkışlarını belirledim.

Bu aşamadan sonra TIA Portal üzerinden programı yazmaya başladım.Uygulamayı simülasyon üzerinden yapacağım için PLC olarak S7-1500 ekledim. S7-1200’deki simülasyonda PID simülasyonu yapılamıyor. Main içinde start ve stop butonunun görevlerini tanımladım.

Daha sonra göstergeler ve potansiyometreler için programı yazdım. Simülasyon programında potansiyometreler 0.0-10.0 arasında değer verdiği için ölçekleme işlemlerini ona göre yaptım. PID kontrolcüyü yüzdelik olarak ayarlayacağım için set değerinde yüzdelik set değeri de belirledim.


Daha sonra cyclic interrupt(100 ms) açarak PID fonksiyonu ekledim ve ayarlarını yaptım.

PID fonksiyonunu çıkarmak için commissioning kısmında önce pretuning yaparak istenilen set değerine getirdim ve daha sonra fine tuning yaparak PID grafiğini çizdirdim. Fine tuning sırasında grafiği çıkarmak için fonksiyon sürekli olarak deneme-yanılma yapıyor. Bu kısım benim fonksiyonum için yaklaşık 30dk sürdü.


Fine tuning bittikten sonra program tamamlanmış oldu ve videodaki halini aldı.
Butgemdeki deney setlerinde S7-1200 ve PWM kullanarak motoru sürdüğüm tank otomasyonu uygulamanın videosu da aşağıdadır.
Bu uygulamada 2 robot ile konveyörden gelen parçayı önce masa üzerine istenilen şekilde dizip daha sonra diğer robot ile kaynağını yaptırdım. Kaynağı yapılan parça ise başka bir bölümde masa üzerine dizildi. Uygulamanın çalışma şekli alttaki gibidir.
Bu uygulamada konveyör ve kaynak için 2 farklı smartcomponent kullandım.


Daha sonra 2 robotu birbiri ile haberleştirmek ve smartcomponentler ile bağlantı kurabilmek için 2 robotun da “controller”ına gerekli sinyalleri ekledim.
Daha sonra 2 robot için farklı 2 RAPID kodu yazdım. İlk robot dizme işi yaptığı için for döngüsü kullandım. 3 adımda gerçekleştiği için ve her adımda farklı noktalara gitmesi gerektiği için de IF şartları belirledim. Diğer robot da sürekli olarak diğer robotu bekleyeceği ve sırası geldiğinde çalışacağı için WHILE ile sürekli döngü içinde kalmasını sağladım.
1.Robot için RAPID kodu:
WaitDI BASLA,1;
Reset kaynak_yap;
Reset Gripper;
FOR z FROM 0 to 2 DO
FOR y FROM 0 to 1 DO
FOR x FROM 0 to 1 DO
FOR i FROM 0 TO 2 DO
MoveL home,v1000,fine,Servo\WObj:=wobj0;
MoveL parca_alma_yaklasim,v1000,fine,Servo\WObj:=wobj0;
WaitDI Parca_sensor,1;
MoveL parca_alma,v100,fine,Servo\WObj:=wobj0;
WaitTime 0.5;
SetDO Gripper,1;
MoveL parca_alma_yaklasim,v100,fine,Servo\WObj:=wobj0;
MoveL home,v1000,fine,Servo\WObj:=wobj0;
MoveL masa_ust,v1000,fine,Servo\WObj:=Workobject_3;
IF i=0 THEN
MoveL parca_birakma1_yaklasim,v1000,fine,Servo\WObj:=Workobject_3;
MoveL parca_birakma1,v100,fine,Servo\WObj:=Workobject_3;
Reset Gripper;
MoveL parca_birakma1_yaklasim,v100,fine,Servo\WObj:=Workobject_3;
MoveL masa_ust,v1000,fine,Servo\WObj:=Workobject_3;
ELSEIF i=1 THEN
MoveL parca_birakma2_yaklasim,v1000,fine,Servo\WObj:=Workobject_3;
MoveL parca_birakma2,v100,fine,Servo\WObj:=Workobject_3;
Reset Gripper;
MoveL parca_birakma2_yaklasim,v100,fine,Servo\WObj:=Workobject_3;
MoveL masa_ust,v1000,fine,Servo\WObj:=Workobject_3;
ELSEIF i=2 THEN
MoveL parca_birakma3_yaklasim,v1000,fine,Servo\WObj:=Workobject_3;
MoveL parca_birakma3,v100,fine,Servo\WObj:=Workobject_3;
Reset Gripper;
MoveL parca_birakma3_yaklasim,v100,fine,Servo\WObj:=Workobject_3;
MoveL masa_ust,v1000,fine,Servo\WObj:=Workobject_3;
Set kaynak_yap;
WaitTime 0.5;
Reset kaynak_yap;
WaitDI Kaynak_devam,1;
WaitTime 0.5;
MoveL parca_birakma3_yaklasim,v1000,fine,Servo\WObj:=Workobject_3;
MoveL parca_birakma3,v100,fine,Servo\WObj:=Workobject_3;
SetDO Gripper,1;
MoveL parca_birakma3_yaklasim,v1000,fine,Servo\WObj:=Workobject_3;
MoveL dizme_ust,v1000,fine,Servo\WObj:=wobj0;
dizme_yaklasim_offs := Offs(dizme_yaklasim,x*300,y*300,z*42);
dizme_offs := Offs(dizme,x*300,y*300,z*40);
MoveL dizme_yaklasim_offs,v1000,fine,Servo\WObj:=wobj0;
MoveL dizme_offs,v100,fine,Servo\WObj:=wobj0;
Reset Gripper;
MoveL dizme_yaklasim_offs,v1000,fine,Servo\WObj:=wobj0;
MoveL dizme_ust,v1000,fine,Servo\WObj:=wobj0;
MoveL home,v1000,fine,Servo\WObj:=wobj0;
ENDIF
ENDFOR
ENDFOR
ENDFOR
ENDFOR
2.Robot için RAPID kodu:
WHILE TRUE DO
WaitDI kaynak_basla,1;
MoveL home,v1000,fine,Weldgun\WObj:=wobj0;
MoveL masa_ust_kaynak,v1000,fine,Weldgun\WObj:=wobj0;
kaynak_1;
MoveL masa_ust_kaynak,v1000,fine,Weldgun\WObj:=wobj0;
kaynak_2;
MoveL masa_ust_kaynak,v1000,fine,Weldgun\WObj:=wobj0;
MoveL home,v1000,fine,Weldgun\WObj:=wobj0;
Set kaynak_bitti;
WaitTime 1;
Reset kaynak_bitti;
ENDWHILE
Bu projede endüstriyel robotları programlamak için tasarlanan RobotStudio programını kullanarak bir palet dizme uygulaması yaptım. Bu uygulama simülasyonda konveyörden gelen ürünleri palete dizerek paletleme işlemini gerçekleştiriyor. Projenin çalışma şekli alttaki videodan görülebilir.
Robotu programlamadan önce “SmartComponent” oluşturarak konveyör ve vakum aletinin çalışma şekillerini simüle etmemiz gerekiyor.

Smartcomponent dizaynını şekildeki gibi yaparak konveyörden parça ilerlemesi ve gerekli sinyal gönderildiğinde vakum aletinin parçayı tutması sağlanıyor.
Daha sonra gerekli sinyaller “controller”a eklenerek robotun program esnasında komutlar göndereceği sinyaller belirlenmiş oluyor. “VAKUM”,”DEVAM”,”YENI_PARCA” sinyalleri ekleniyor.
Daha sonra robotun RAPID kodu yazılarak ve noktalar belirlenerek robotun hareket sırası ve hareket özellikleri belirleniyor. Bu uygulamada dizme olduğu için bırakma noktasını her yeni parçada ötelemek gerekiyor. Bunun için de for döngüleri kullanılıyor.
WaitDI BASLA,1;
FOR z FROM 0 TO 1 DO
FOR y FROM 0 TO 2 DO
FOR x FROM 0 TO 3 DO
SetDO YENI_PARCA,1; !yeni parça gelmesi için puls sinyal gönderiliyor.
WaitTime 0.5;
SetDO YENI_PARCA,0;
MoveL home,v2000,z10,Vacuum_Tool_TCP\WObj:=wobj0;
WaitDI DEVAM,1;
MoveL teneke_alma_nok,v2000,z10,Vacuum_Tool_TCP\WObj:=palet_wobj;
WaitTime 0.5;
SetDO VAKUM,1;
MoveL home,v1000,z10,Vacuum_Tool_TCP\WObj:=wobj0;
birakma_origin_nok_offs:= Offs(birakma_origin_nok,x*254,y*203,z*301);
yaklasim_nok:= Offs(birakma_origin_nok_offs,0,0,240);
MoveL yaklasim_nok,v2000,z10,Vacuum_Tool_TCP\WObj:=palet_wobj;
WaitTime 0.5;
MoveL birakma_origin_nok_offs,v500,z10,Vacuum_Tool_TCP\WObj:=palet_wobj;
WaitTime 1;
SetDO VAKUM,0;
WaitTime 0.5;
MoveL yaklasim_nok,v2000,z100,Vacuum_Tool_TCP\WObj:=palet_wobj;
ENDFOR
ENDFOR
ENDFOR
MoveL home,v1000,z100,Vacuum_Tool_TCP\WObj:=wobj0;
Bu uygulama ile programda işlenilen görüntüdeki en büyük nesneyi tanıyıp kullanıcıya göstermesini amaçladım. Bu uygulamanın daha verimli çalışması için programa verilen görüntüdeki arkaplan ve nesnelerin renklerinin birbirine çok yakın olmaması gerekiyor. İlk deneme yaptığım fotoğrafı kendim çektiğim için arkaplan ışıklandırması çok iyi olmadı. O yüzden daha gri bir arkaplan oluştu. Arkaplan renginin yapılacak işlemi bozmaması için program içinden “threshold” değeri ayarlanmalıdır.

İşlemin daha verimli çalışması için fotoğraf önce terslenerek arkaplanın siyaha en yakın değere getiriyoruz. Daha sonra “grayscale” işlemi uygulayarak renklerden arındırıyoruz. Son işlem olarak da siyahların tamami ile siyah olması ve nesnelerin tamami ile beyaz gözükmesi için bir “threshold” işlemi uyguluyoruz. Fotoğrafın hesaplama yapılan hali sağ alttaki halidir.
Fotoğraf diğer işlemlerin yapılması için hazır hale getirildikten sonra “contour” bulma işlemi uygulanıyor. Bu işlem ile nesneler arkaplana zıt renkte olduğu için tanınmış oluyor. Daha sonra her bulunun “contour” tek tek çizdirilip alanları hesaplanıyor ve üstlerine yazdırılıyor. Hesaplanan alanlar karşılaştırmaya tabi edilip en büyük alan ortaya çıkarılıyor. En büyük alana sahip olan nesne yeniden farklı bir renk ile belirtiliyor.


Eğer fotoğrafta beyaza çok yakın nesneler var ise üstteki resimdeki sağdaki tornavida gibi bozulmalar olabiliyor.
Programın kodu da aşağıdaki gibi:
import cv2
import numpy as np
#Çalışma bölgesini hazırlama
frame = cv2.imread("foto.jpg")
frame_small = cv2.resize(frame, (600, 400))
frame_reversed = cv2.bitwise_not(frame_small)
frame_gray = cv2.cvtColor(frame_reversed, cv2.COLOR_BGR2GRAY)
_, threshold = cv2.threshold(frame_gray, 120, 255, cv2.THRESH_BINARY)
#Parçaları belirleme
_, contours, hierarchy = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
area_list = []
for cnt in contours:
(x, y, w, h) = cv2.boundingRect(cnt)
area = cv2.contourArea(cnt)
area_list.append(area)
maks_index = np.argmax(area_list)
if area>30:
cv2.putText(frame_small,str(area), (x,y-5), 2, 0.8, (0, 255, 0), 1)
cv2.rectangle(frame_small, (x, y), (x + w, y + h), (0, 255, 0), 2)
#Büyük parçayı yazdırma
print("maks: ", max(area_list))
(x_max, y_max, w_max, h_max) = cv2.boundingRect(contours[maks_index])
cv2.rectangle(frame_small, (x_max, y_max) , (x_max + w_max, y_max + h_max), (0, 0, 255), 2)
cv2.putText(frame_small, str(max(area_list)) , (x_max,y_max-5), 2, 0.8,(0, 0, 255), 1 )
#Sonuç Gösterme
cv2.imshow("Original", frame_small)
cv2.imshow("Gray", frame_gray)
cv2.imshow("Reversed", frame_reversed)
cv2.imshow("Threshold", threshold)
cv2.waitKey(0)
cv2.destroyAllWindows()
Bu uygulama ile bilgisayarımın işlemci sıcaklık ve fan dönüş hızı değerleri ile ekran kartımın sıcaklık ve fan dönüş hızı değerlerini bilgisayara USB portu üzerinden bağlı olan NodeMCU’ya aktardım. NodeMCU’ya da OLED bir ekran bağlayarak ekran üzerinden bu değerleri izleyebileceğim bir uygulama yaptım.

Bu projede kullandığım parçalar:
Bu uygulamada bilgisayar mikrokontrolcüye veri göndermesi gerektiği için 2 ayrı program yazmam gerekti. Mikrokontrolcü direkt olarak sistem sıcaklık ve fan değerlerine erişemeyeceği için böyle bir yol izledim. İlk aşama olarak python ile sistem sıcaklık ve fan dönüş hızı değerlerini seriport üzerinden mikrokontrolcüye yollamam gerekti. Onun için yazdığım script aşağıdadır. Sistem bilgilerini alabilmek için bu sistem çalışırken arkaplanda OpenHardwareMonitör çalışıyor olmalı.
import wmi
import serial
import time
w = wmi.WMI(namespace="root\OpenHardwareMonitor")
while True:
sensor_infos = w.Sensor()
ser = serial.Serial("COM4", 9600)
for sensor in sensor_infos:
if sensor.SensorType=='Temperature':
if sensor.Name == "CPU Package":
cpu_temp = int(sensor.Value)
if sensor.Name == "GPU Hot Spot":
gpu_temp = int(sensor.Value)
for sensor in sensor_infos:
if sensor.SensorType=='Fan':
if sensor.Name == "Fan #1":
cpu_fan = int(sensor.Value)
if sensor.Name == "GPU Fan":
gpu_fan = int(sensor.Value)
print("Cpu Temp:" , cpu_temp)
print("Gpu Temp:" , gpu_temp)
print("Cpu Fan:" , cpu_fan)
print("Gpu Fan:" ,gpu_fan)
data = ("=================\n" + "Cpu Temp: " + str(cpu_temp) + "\n" + "Gpu Temp: " + str(gpu_temp) + "\n" + "Cpu Fan: " + str(cpu_fan) + "\n" + "Gpu Fan: " + str(gpu_fan) + "\n" + "=================\n" + "-" + "\n")
time.sleep(2)
ser.write(data.encode())
time.sleep(2)
ser.close()
time.sleep(2)
Bu script ile seriport açıp yazdırılacak değerleri mikrokontrolcü tarafına yolladım. Bütün değerleri tek parça halinde yollamamın nedeni ekrana aynı anda sadece tek bir bilgi yazdırabiliyor olmamdı. NodeMCU için yazdığım kod ise aşağıdaki gibidir.
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_MOSI 14
#define OLED_CLK 12
#define OLED_DC 13
#define OLED_CS 0
#define OLED_RESET 15
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
String readString;
void setup() {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC);
display.display();
delay(1000);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
}
void loop() {
while (Serial.available()) {
if (Serial.available() >0)
{
char c = Serial.read();
readString += c;
if (splitter == '-')
{
delay(2000);
readString="";
display.clearDisplay();
digitalWrite(15,HIGH);
delay(2500);
}
}
display.clearDisplay();
display.setCursor(0,0);
display.print(readString);
display.display();
delay(100);
}
}
Ekran sürücüsü AdaFruit olduğu için internet sitesinden ekran kütüphaneleri indirdim. Öncelikle kütüphaneleri ekledim ve pin tanımlamalarını yaptım. setup() kısmında font büyüklüğü ve renk ayarlamaları yaptım ve ekranı kullanılabilir hale getirdim. loop içinde de seri haberleşme sağlandığı zaman seriport üzerinden bilgileri karakter olarak alıp bir string içine yazdırdım. Daha sonra bu string formatındaki veriyi de ekrana yazdırdım. Python kodu içinde her veri setini ayırmak için veri seti sonunda “-” karakterini yolladım. NodeMCU kodunda da “-” karakteri geldiği zaman ekran ve veri sıfırlanıyor. Yeni bir verisetinin gelmesine hazır hale gelmiş oluyor.
Ekranın nasıl çalıştığına dair videoyu aşağıdan görebilirsiniz.
Bu yazımda Selenium modülünü kullanarak yazdığım bir alışveriş ürün arama botu programını paylaşacağım. Bu programda iki farklı arama kategorisi oluşturdum. Teknoloji ve giyim mağazaları olarak ikiye ayırdım. Her iki tür için de üçer adet websitesini kullandım. Websitesi sayısı kolaylıkla arttırılabilir veya kategori eklenebilir. Program genel olarak aşağıdaki videodaki şekilde çalışıyor.
Programın kodu da aşağıdaki şekilde:
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
##Kullanıcıdan bilgiler alınıyor.
tur = input("Teknoloji mağazaları - 1\nGiyim mağazaları - 2\nSeçiminiz: ")
urun = input("Aramak istediğiniz ürün: ")
if tur == "1":
##Bu kısımda uygulamanın chromeda açılması ve açıldığı gibi tam ekran olması sağlanıyor.
browser = webdriver.Chrome()
browser.maximize_window()
##ilk site için siteye girildikten sonra arama barına girilen ürün bilgisi atanıp arama tuşuna basılıyor.
browser.get("http://www.vatanbilgisayar.com")
time.sleep(2)
browser.find_element_by_xpath("//*[@id='navbar-search-input']").send_keys(urun)
browser.find_element_by_xpath("/html/body/header/nav/div[3]/div/div/div/div[2]/div[2]/div/div/button").click()
time.sleep(2)
##İkinci sekme açılıp ürün bilgisi arama barına girilip ENTER tuşuna basılıyor.
browser.execute_script("window.open('about:blank', 'tab2');")
browser.switch_to.window("tab2")
browser.get('http://www.mediamarkt.com.tr')
time.sleep(2)
browser.find_element_by_xpath("//*[@id='search-autocomplete']/form/input[1]").send_keys(urun)
time.sleep(1)
browser.find_element_by_xpath("//*[@id='search-autocomplete']/form/input[1]").send_keys(Keys.RETURN)
time.sleep(2)
##Üçüncü sekme açılıp ürün bilgisi arama barına girilip ENTER tuşuna basılıyor.
browser.execute_script("window.open('about:blank', 'tab3');")
browser.switch_to.window("tab3")
browser.get('http://www.hepsiburada.com')
time.sleep(2)
browser.find_element_by_xpath("//*[@id='SearchBoxOld']/div/div/div[1]/div[2]/input").send_keys(urun)
time.sleep(1)
browser.find_element_by_xpath("//*[@id='SearchBoxOld']/div/div/div[1]/div[2]/input").send_keys(Keys.RETURN)
time.sleep(1)
print("Arama İşlemi Tamamlandı.")
elif tur == "2":
browser = webdriver.Chrome()
browser.maximize_window()
##ilk site için siteye girildikten sonra arama barına girilen ürün bilgisi atanıp ENTER tuşuna basılıyor.
browser.get("http://www.koton.com")
time.sleep(2)
browser.find_element_by_xpath("//*[@id='search']").send_keys(urun)
time.sleep(1)
browser.find_element_by_xpath("//*[@id='search']").send_keys(Keys.RETURN)
time.sleep(1)
##İkinci sekme açılıp ürün bilgisi arama barına girilip ENTER tuşuna basılıyor.
browser.execute_script("window.open('about:blank', 'tab2');")
browser.switch_to.window("tab2")
browser.get("https://www.lcwaikiki.com/")
time.sleep(2)
browser.find_element_by_xpath("//*[@id='search']").send_keys(urun)
time.sleep(1)
browser.find_element_by_xpath("//*[@id='search']").send_keys(Keys.RETURN)
time.sleep(1)
##Üçüncü sekme açılıp ürün bilgisi arama barına girilip ENTER tuşuna basılıyor.
browser.execute_script("window.open('about:blank', 'tab3');")
browser.switch_to.window("tab3")
browser.get("https://www.trendyol.com/")
time.sleep(2)
browser.find_element_by_xpath("//*[@id='auto-complete-app']/div/div[1]/input").send_keys(urun)
time.sleep(1)
browser.find_element_by_xpath("//*[@id='auto-complete-app']/div/div[1]/input").send_keys(Keys.RETURN)
time.sleep(1)
print("Arama İşlemi Tamamlandı.")
else:
print("Yanlış Seçim")
Bu yazıda edabit.com üzerinde gördüğüm problemlerden kendim ilginç bulduğum ve çözmeye çalıştıklarımı paylaşacağım.
1-Disarium Sayısı Kontrolü
Bir n sayısının rakamları soldan sağa doğru bulunduğu sıradaki kuvveti alınıp toplandığında elde edilen sonuç n sayısına eşit oluyorsa bu sayıya Disarium sayısı denir. 89, 135, 518 gibi.
Örneğin; 135 sayısı için
1^1 + 3^2 + 5^3 = 1 + 9 + 125 = 135
olduğu için 135 disarium sayısıdır. Bu sayının kontrolü için de aşağıdaki kod parçasını yazdım.
def is_disarium(sayi):
liste = []
for i in str(sayi):
liste.append(i)
a=0
for j in range(0,len(liste)):
a += int(liste[j])**(j+1)
if sayi == a:
return True
else:
return False
print(is_disarium(135))
Çıktı: True
2-KRİPTOLAMA ÖRNEĞİ
Girilen bir kelimeyi önce ters çevirecek sonra aşağıdaki değişimleri yapıp sonuna “gkhn” ekleyecek kod parçasını yazdım.
# a => 0 # e => 1 # i => 2 # o => 2 # u => 3
a = str(input("Şifrelenicek kelimeyi giriniz: "))
def kripto(kelime):
liste = []
for i in kelime:
liste.append(i)
liste.reverse()
listetostr = ''.join(map(str,liste))
listetostr = listetostr.replace("a", "0")
listetostr = listetostr.replace("e", "1")
listetostr = listetostr.replace("i", "2")
listetostr = listetostr.replace("o", "2")
listetostr = listetostr.replace("u", "3")
listetostr = listetostr + "gkhn"
return listetostr
print(kripto(a))
Çıktı: “denemeakgozgokhan” –> n0hk2gz2gk01m1n1dgkhn
3-KART OYUNU
Verilen iki adet 5’li kart dizisine göre kartların toplamı büyük olan kazanıcak şekilde yazdığım kod parçası.
def win_round(list1,list2):
list1 = sorted(list1)
list2 = sorted(list2)
sayi1 = str(list1[-1]) + str(list1[-2])
sayi2 = str(list2[-1]) + str(list2[-2])
print("Senin kartlarının toplamı: " + sayi1)
print("Rakibinin kartlarının toplamı: " + sayi2)
if int(sayi1)>int(sayi2):
print("Kazandın! " + sayi1 + ">" + sayi2)
elif int(sayi1)<int(sayi2):
print("Kaybettin :( " + sayi1 + "<" + sayi2)
else:
print("Berabere")
return
win_round([7,3,4,4,5],[3,2,5,4,6])
Çıktı :
Senin kartlarının toplamı: 75
Rakibinin kartlarının toplamı: 65
Kazandın! 75>65