İçindekiler:
2025 Yazar: John Day | [email protected]. Son düzenleme: 2025-01-13 06:58
Tanıtım
Sihirli El, engelli ve motor beceri bozukluğu olan kişilerin simüle edilmiş bir ortamda çizim ve yazma yaratıcılığının keyfini çıkarmasını sağlar. Sihirli El, işaret parmağınızın hareketini algılayan ve bunu bilgisayar ekranında çizgi çizmeye çeviren giyilebilir bir eldivendir.
İhtiyac duyulan malzemeler
LSM9DOF Breakout Board --- 24,95 $ ---
Wifi ile Adafruit Tüy --- 18,95 $ ---
Dişi/Dişi Teller --- 1,95 $ ---
Bant/Velcro şeritler --- 3 $
Eşit güçte iki mıknatıs --- Fiyatlar değişiklik gösterir
Nasıl çalışır
Bir ivme ölçer kullanarak, kullanıcının parmağının ne zaman yukarı ve aşağı hareket ettiğini belirlememize yardımcı olacak y ekseni için hızlanma verileri toplayabiliriz. İvme ölçerimiz ivmeyi dünyanın merkezine göre ölçtüğü için x ekseninin (sol veya sağ) ivmesini belirleyemiyoruz. Neyse ki LSM9DOF devre kartı aynı zamanda manyetik alanlar hakkında veri toplamamızı sağlayan bir manyetometre içerir. 30 cm arayla iki mıknatıs yerleştiriyoruz ve arada eldiven var. Manyetik veriler pozitif olarak okunursa, eldivenin sağa doğru hareket ettiğini ve bunun tersini biliyoruz. Tüm veriler ivmeölçer/manyetometrede toplandıktan sonra verileri tel aracılığıyla bir wifi bilgisayarına bağlı olan tüye gönderir ve ardından verileri daha sonra kodumuzda kullanabileceğimiz bilgisayara iletir.
Adım 1: Fiziksel Prototip 1
Bu prototipin, elektronik cihazların üzerinden kayması için elde gevşek bir şekilde dikilmiş eldiven olması amaçlanmıştır. Elektronik cihaz daha sonra eldeki temel eldivenle birlikte zırh altı manşon tabanına cırt cırt ile bağlanacaktır. Sonra yeşil eldiven tabanın ve elektronik cihazların üzerinden kayacak….
Prototip eldiven yapma adımları:
- Elinizi takip edecek kadar büyük iki parça kumaş alın
- Elinizi her iki kumaş parçasına da sürün ve kesin
- İki el kesimini mükemmel bir şekilde hizalanacak şekilde bir araya getirin
- Ardından, dikiş makinesini hazırlamak için ipliği makinede belirtilen noktalardan geçirin.
- Dikiş makinesi kurulduğunda, iğneyi kaldırın ve birleştirilen iki kumaş parçasını iğnenin altına yerleştirin.
- İğnenin kumaşın en kenarında hizalandığından emin olun, makineyi çalıştırın ve bir elin sığabilmesi için iki parçayı bilekte dikmeden bırakarak kumaşın kenarları boyunca dikin.
Adım 2: Fiziksel Prototip 2
Son prototipimiz, her bileğe göre ayarlanabilen Velcro kayışla birleştirilmiş normal bir eldivendir. Eldiven ve kayış birbirine dikilir ve elektronik cihazlar eldivene Velcro ile bağlanır.
Eldivenin 2. prototipini yapma adımları:
- Bir eldiven satın alın, eldivenin malzemesi önemli değil.
- Velcro bilek kayışı satın alın
- Taşınabilir bir pil satın alın
- Yapışkan Velcro satın alın
- Bir dikiş iğnesi ile cırt cırtlı bilek kayışını eldivenin tabanına takın.
- Bilek kayışı farklı bilek boyutlarına göre ayarlanabilmelidir.
- Yapışkan bandı ivmeölçerin tabanına yapıştırın ve eldivenin işaret parmağına yapıştırın.
- Kuş tüyüne yapışkan bant yapıştırın ve eldivenin üstüne yapıştırın.
- Kabloları kullanarak geçişteki 3V3 pinini ivmeölçerdeki VIN pinine bağlayın
- Kabloları kullanarak tüydeki GND pimini ivmeölçerdeki GND pimine bağlayın.
- Kabloları kullanarak geçişteki SCL pimini ivmeölçerdeki SCL pimine bağlayın.
- Kabloları kullanarak geçişteki SDA pimini ivmeölçerdeki SDA pimine bağlayın.
- Güç sağlamak için USB üzerinden en az 5 voltluk bir pili tüye bağlayın.
3. Adım: Mıknatıslar
Adım 1: Eşit kuvvette iki mıknatısı karşı karşıya koyun.
Adım 2: İki mıknatıs arasındaki 30 cm'lik boşluğu ölçün
Adım 3: Manyetometreyi tam olarak iki mıknatısın ortasına yerleştirin. Ortadayken 0 civarında veri almalısınız. Sıfır okuması alırsanız 5. adıma geçin.
Adım 4: Okuma sıfır değilse veya sıfıra yakınsa, mıknatısların mesafesini ayarlamanız gerekir. Okuma negatifse, sol mıknatısı bir cm veya 2 sola veya okuma sıfır olana kadar hareket ettirin. Pozitif ise, doğru mıknatıs dışında aynı şeyi yapın.
Adım 5: Manyetometreden gelen verileri kabul eden ve pozitif veya negatif olup olmadığını okuyan kodu yazın. Pozitif ise, kod sağa bir çizgi çizin ve negatif ise sola bir çizgi çizin.
4. Adım: Kod
github.iu.edu/ise-e101-F17/MuscleMemory-Sw…
Tanıtım:
İvmeölçerden gelen verileri işleyebilmek için Adafruit tüyü ile verileri işleyen sunucu (dizüstü/masaüstü üzerinde çalışan) arasında bir istemci/sunucu ilişkisi kurulmalıdır. İki kod dosyasının oluşturulması gerekecektir: biri istemci için (Adafruit tüyü) ve diğeri sunucu için (bu durumda Jarod'un dizüstü bilgisayarı). İstemci C++ ile yazılmıştır ve sunucu python ile yazılmıştır. Arduino, esas olarak bir C++ dili olduğu için müşteri için kullanılan dil önemlidir ve onu farklı bir dil kullanmak için değiştirmek zordur. Sunucu, ağ özelliklerine sahip olduğu sürece herhangi bir dilde yazılabilir.
İstemciyi Ayarlama:
İlk olarak, istemci kodunu ayarlayacağız. WiFi bağlantı kodunun çoğuna Adafruit kitaplıkları aracılığıyla kolayca erişilebilir. İlgili sınıfları dahil ederek başlıyoruz.
#include #include #include #include #include
Kod boyunca kullanılacak bazı değişkenleri ayarlayın.
// Bir ağa bağlanın const char* ssid = "MMServer"; const char* şifre = "MMServer-Şifre"; // Verileri alacak sunucunun IP ve portu const char* host = "149.160.251.3"; const int bağlantı noktası = 12347; bool bağlı = yanlış;
// Hareket dedektörünü başlat
Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0(1000);
WiFiClient istemcisi;
Geçiş yumuşatma başlar başlamaz çalıştırılacak bir setup() işlevi oluşturun.
// WiFi bağlantısını kurun ve servervoid setup()'a bağlanın { Serial.begin(9600); gecikme(100);
Seri.println();
Seri.println(); Serial.print("Bağlanıyor"); Serial.println(ssid); // WiFi WiFi'yi başlat.begin(ssid, password); // Bağlanıyor… while (WiFi.status() != WL_CONNECTED) { gecikme(500); Seri.print("."); } // WiFi Serial.println(""); Serial.println("WiFi bağlandı"); Serial.println("IP adresi: "); Serial.println(WiFi.localIP());
#ifndef ESP8266
while(!Seri); #endif Serial.begin(9600); Serial.println("Sensör Testi");
// Sensörü başlat
if(!lsm.begin()) { // LSM9DS0 Serial.print'i algılarken bir sorun oluştu(F("Hata, LSM9DS0 algılanmadı… Kablolamanızı veya I2C ADDR'nizi kontrol edin!")); süre(1); } Serial.println(F("LSM9DS0 9DOF Bulundu")); // Sunucuya bağlanmaya başla Serial.print("Bağlanıyor "); Serial.println(ana bilgisayar);
// Başarılı bağlantı olup olmadığını kontrol edin. Başarısız olursa iptal et
if (!client.connect(host, port)) { Serial.println("bağlantı başarısız"); bağlı = yanlış; dönüş; } başka { bağlı = doğru; }
//Sensör kazancını ve entegrasyon süresini ayarla
configureSensor(); }
Daha sonra tekrar tekrar döngü yapacak bir döngü işlevine ihtiyacımız var. Bu durumda ivmeölçerden sunucuya tekrar tekrar “[z_accel]:[y_mag]:[z_mag]” şeklinde veri göndermek için kullanılır. client.print(sayılar); işlevi, sunucuya veri gönderen şeydir.
geçersiz döngü() {gecikme(250); if(connected){ // Bu, verileri sunucuya gönderecek sensor_event_t accel, mag, gyro, temp; lsm.getEvent(&accel, &mag, &gyro, &temp); Dize numaraları; sayılar += accel.acceleration.z; sayılar += ":"; sayılar += mag.magnetic.y; sayılar += ":"; sayılar += mag.magnetic.z; Seri.baskı(sayılar); client.print(sayılar); Seri.println(); } else {installConnection(); } }
Bazı yardımcı fonksiyonlar için, tüy ve sunucu arasındaki bağlantıyı kurmak için birine ihtiyacımız var.
void setupConnection(){ if (!client.connect(host, port)) { Serial.println("bağlantı başarısız"); bağlı = yanlış; dönüş; } başka { bağlı = doğru; } }
Ayrıca sensörü yapılandırmamız ve okuyacağı değer aralığını vermemiz gerekiyor. Örneğin, hızlanmanın aralık için 5 seçeneği vardır: 2g, 4g, 6g, 8g ve 16g.
void configureSensor(void){ // İvmeölçer aralığını ayarlayın //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_2G); lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_4G); //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_6G); //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_8G); //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_16G); // Manyetometre hassasiyetini ayarlayın //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_2GAUSS); //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_4GAUSS); //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_8GAUSS); lsm.setupMag(lsm. LSM9DS0_MAGGAIN_12GAUSS);
// Jiroskopu ayarla
lsm.setupGyro(lsm. LSM9DS0_GYROSCALE_245DPS); //lsm.setupGyro(lsm. LSM9DS0_GYROSCALE_500DPS); //lsm.setupGyro(lsm. LSM9DS0_GYROSCALE_2000DPS); }
Sunucunun Kurulumu:
Sunucu, bir bilgisayarın komut satırında çalışacak bir python dosyası olacaktır. Başlamak için gerekli sınıfları içe aktarın.
Socketimport'u yeniden içe aktar pyautogui'yi içe aktar
soket ağ için kullanılır. re, normal ifade veya dize işlemleri için kullanılır. pyautogui, çizimin gerçekleşmesine izin verecek bir python kütüphanesidir (daha sonra tartışılacaktır).
Ardından, bazı değişkenleri tanımlamalıyız. Bunlar global değişkenler olacak, bu yüzden birden fazla fonksiyonda erişilecekler. Daha sonra kodda kullanılacaklar.
i = 0n = 0 satır = 1
data_list =
mag_data =
mag_calib_y = 0 mag_offset_y = 0
z_calib = 0
z_offset = 0 z_moving_offset = 0 z_diff = 0 z_real = 0 z_velo = 0 z_pos = 0
keep_offset = Yanlış
first_data = Doğru
Şimdi bir sunucu oluşturmak ve onu gelen bağlantılar için açmak için bir fonksiyona ihtiyacımız var.
def startServer(): global i global first_data # initialize server socket serversocket = socket.socket(socket. AF_INET, socket. SOCK_STREAM) serversocket.setsockopt(socket. SOL_SOCKET, socket. SO_REUSEADDR, 1) # Sunucu IP adresi ve bağlantı noktası ana bilgisayarı = " 149.160.251.3" bağlantı noktası = 12347 sunucu_adresi = (ana bilgisayar, bağlantı noktası) # Sunucuyu açın ve gelen bağlantıları dinleyin yazdır ('Sunucu %s bağlantı noktasından başlatılıyor' % server_address) serversocket.bind(sunucu_adresi) serversocket.listen(5) # Bağlantıları bekleyin… while True: print ('Bağlantı bekleniyor…') # Gelen bir bağlantıyı kabul edin (clientsocket, adres) = serversocket.accept() # Alınan verileri ayrıştırmayı deneyin try: print ('Bağlantı kuruldu ', adres) while True: # Veriyi alın ve veri işlemek için gönderin = clientsocket.recv(25) accel_data = re.split('[:]', str(data)) accel_data[0] = accel_data[0][2:] accel_data[1] = accel_data[1] accel_data[2] = accel_data[2][1:-1] print(accel_data) i+=1 if(i < 51): calibData(accel_data) else: moveAcce l(accel_data[0]) processData(accel_data) first_data = Son olarak yanlış: # Gereksiz veri sızıntısını önlemek için soketi kapatın clientsocket.close()
Şimdi tüm verileri işleyecek fonksiyonlara ihtiyacımız var. Atılması gereken ilk adım ve çağrılan ilk fonksiyon, hesaplama amacıyla sensörün kalibrasyonudur.
def calibData(list): global z_calib global z_offset global mag_data global mag_calib_y global mag_offset_y z_calib += float(list[0]) mag_calib_y += float(list[1]) if(i==50): z_offset = z_calib / 50 mag_offset_y = mag_calib_y / 50 z_calib = 0 mag_calib_y = 0 mag_data.append(mag_offset_y)
Ardından, hareketli bir hızlanma ofseti oluşturuyoruz. Bu, programın, birinin parmağını hareket ettirmeyi bıraktığında algılamasını sağlar, çünkü sunucuya gönderilen tüm hızlandırma değerleri o anda aynı olmalıdır.
def moveAccel(num): global z_calib global z_diff global z_moving_offset global z_offset global data_list global n global keep_offset if(n 0.2 veya z_diff < -0.2): # veri içinde hareket algılandı, yeniden başlat keep_offset = True n = 0 z_calib = 0 z_moving_offset = 0 z_diff = 0 data_list = keep_offset değilse mola: # veride sabit, yeni z_offset ayarla z_offset = z_moving_offset print("Yeni z_offset: ") print(z_offset) n = 0 z_calib = 0 z_moving_offset = 0 zlist_diff = [0 data_] keep_offset = Yanlış keep_offset = Yanlış
Ardından, matematiğin ağırlığını yapıyoruz. Bu, hızlanma verilerinin, kullanıcının parmağını hareket ettirdiği yönü söylememizi sağlayacak bir konum verisine dönüştürülmesini içerir.
def processData(list): #[accel.z, mag.y] global z_offset global z_real global z_velo global z_pos global first_data global mag_data
z_real = float(list[0]) - z_offset
mag_y = list[1] mag_z = list[2] left = False right = False # Hızlandığından kesinlikle emin olana kadar hızlanmayı işlemeyin # Mekanik gürültünün konuma katkıda bulunmasını önler if(z_real -0.20): z_real = 0 #Begin konum bulmak için entegrasyonlar if(first_data): mag_data.append(mag_y) z_pos = (0,5 * z_real * 0,25 * 0,25) + (z_velo * 0,25) + z_pos z_velo = z_real * 0,25 pyautogui.moveTo(1500, 1000) else: z_pos = (0,5 * z_real * 0,25 * 0,25) + (z_velo * 0,25) + z_pos z_velo = (z_real * 0,25) + z_velo del mag_data[0] mag_data.append(mag_y) if(float(mag_data[1]) - float(mag_data[0]) > 0.03): right = True elif(float(mag_data[1]) - float(mag_data[0]) < -0.03): left = True if(sağ): hareket(50, int(z_pos*) 1000)) elif(sol): hareket(-50, int(z_pos*1000)) z_velo = 0 z_pos = 0
Şimdi, nihayet, imleci hareket ettiriyoruz! Bunun için bir boya penceresi açıp tam ekran yaptık. pyautogui kitaplığı, pyautogui.dragRel(x, y) adlı bir işlev içerir; fare imlecini bir noktadan diğerine sürüklemek için kullandığımız. Göreceli konum verilerini kullanır, böylece hareket imlecin son konumuna göre olur.
def hareket(x, y): print("hareket etme", x, -y) pyautogui.dragRel(x, -y)
Son olarak, tüm bu kodun çalışmasına bile izin vermek için ana işlevi çağırmamız gerekiyor.
# serverstartServer()'ı başlatmak için işlevi çağırır