สารบัญ:

Accel Writing (มือวิเศษ): 4 ขั้นตอน (พร้อมรูปภาพ)
Accel Writing (มือวิเศษ): 4 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: Accel Writing (มือวิเศษ): 4 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: Accel Writing (มือวิเศษ): 4 ขั้นตอน (พร้อมรูปภาพ)
วีดีโอ: บันไดทักษะ 4 ขั้น : วิธีสอนอ่านออกเขียนได้ 2024, พฤศจิกายน
Anonim
การเขียน Accel (มือวิเศษ)
การเขียน Accel (มือวิเศษ)
การเขียน Accel (มือวิเศษ)
การเขียน Accel (มือวิเศษ)
การเขียน Accel (มือวิเศษ)
การเขียน Accel (มือวิเศษ)

บทนำ

Magic Hand ช่วยให้ผู้ทุพพลภาพและผู้บกพร่องทางทักษะการเคลื่อนไหวได้เพลิดเพลินกับความคิดสร้างสรรค์ในการวาดภาพและการเขียนในสภาพแวดล้อมจำลอง Magic Hand เป็นถุงมือที่สวมใส่ได้ซึ่งจะตรวจจับการเคลื่อนไหวของนิ้วชี้ของคุณและแปลเป็นภาพลายเส้นบนหน้าจอคอมพิวเตอร์

วัสดุที่จำเป็น

LSM9DOF กระดานฝ่าวงล้อม --- $24.95 ---

Adafruit Feather พร้อม Wifi --- $18.95 ---

สายหญิง/หญิง --- $1.95 ---

เทป/แถบเวลโคร --- $3

แม่เหล็กแรงเท่ากันสองตัว --- ราคาแตกต่างกันไป

มันทำงานอย่างไร

เมื่อใช้มาตรความเร่ง เราสามารถรวบรวมข้อมูลการเร่งความเร็วสำหรับแกน y ซึ่งจะช่วยให้เราระบุได้ว่านิ้วของผู้ใช้จะเคลื่อนขึ้นและลงเมื่อใด เนื่องจากมาตรความเร่งของเราวัดความเร่งเมื่อเทียบกับจุดศูนย์กลางของโลก เราจึงไม่สามารถระบุความเร่งของแกน x ได้ (ซ้ายหรือขวา) โชคดีที่กระดานฝ่าวงล้อม LSM9DOF ยังมีเครื่องวัดความเข้มข้นของสนามแม่เหล็กซึ่งช่วยให้เราสามารถรวบรวมข้อมูลเกี่ยวกับสนามแม่เหล็กได้ เราวางแม่เหล็กสองตัวห่างกัน 30 ซม. และสวมถุงมือไว้ตรงกลาง หากข้อมูลแม่เหล็กเป็นบวก แสดงว่าถุงมือเคลื่อนที่ไปทางขวาและในทางกลับกัน หลังจากรวบรวมข้อมูลทั้งหมดในมาตรความเร่ง/มาตรแม่เหล็กแล้ว มันจะส่งข้อมูลผ่านสายไปยังขนนกซึ่งเชื่อมต่อกับคอมพิวเตอร์ของ wifi แล้วส่งต่อข้อมูลไปยังคอมพิวเตอร์ซึ่งเราสามารถใช้ในโค้ดของเราได้

ขั้นตอนที่ 1: ต้นแบบทางกายภาพ 1

ต้นแบบทางกายภาพ 1
ต้นแบบทางกายภาพ 1
ต้นแบบทางกายภาพ 1
ต้นแบบทางกายภาพ 1

ต้นแบบนี้มีไว้เพื่อเย็บถุงมือแบบหลวม ๆ บนมือเพื่อให้ลื่นไถลผ่านอุปกรณ์อิเล็กทรอนิกส์ จากนั้นอุปกรณ์อิเล็กทรอนิกส์จะถูกติดด้วยเวลโครกับฐานปลอกแขนใต้เกราะรวมกับถุงมือพื้นฐานในมือ จากนั้นถุงมือสีเขียวจะลื่นเหนือฐานและอุปกรณ์อิเล็กทรอนิกส์….

ขั้นตอนการทำถุงมือต้นแบบ:

  • ได้ผ้าสองชิ้นที่ใหญ่พอที่จะแกะรอยมือ
  • แกะรอยมือลงบนผ้าทั้งสองชิ้นแล้วตัดออก
  • นำมือทั้งสองข้างมาประกบกันให้ชิดกัน
  • ถัดไป เพื่อเตรียมจักรเย็บผ้า ให้ร้อยด้ายผ่านจุดที่ระบุบนเครื่อง
  • เมื่อติดตั้งจักรเย็บผ้าแล้ว ให้ยกเข็มขึ้นแล้ววางผ้าสองชิ้นที่ประกบกันไว้ใต้เข็ม
  • ตรวจสอบให้แน่ใจว่าเข็มถูกเรียงไว้ที่ขอบผ้า สตาร์ทเครื่อง และเย็บตามขอบของผ้า โดยปล่อยให้ทั้งสองชิ้นไม่ได้เย็บไว้ที่ข้อมือเพื่อให้สอดมือได้

ขั้นตอนที่ 2: ต้นแบบทางกายภาพ 2

ต้นแบบทางกายภาพ 2
ต้นแบบทางกายภาพ 2
ต้นแบบทางกายภาพ 2
ต้นแบบทางกายภาพ 2

ผลิตภัณฑ์ต้นแบบขั้นสุดท้ายของเราคือถุงมือธรรมดาที่ประกอบเข้ากับสายรัดเวลโครที่ปรับได้กับข้อมือทุกแบบ ถุงมือและสายรัดถูกเย็บเข้าด้วยกัน และติดอุปกรณ์อิเล็กทรอนิกส์เข้ากับถุงมือด้วยเวลโคร

ขั้นตอนการทำถุงมือต้นแบบที่ 2

  1. ซื้อถุงมือ วัสดุของถุงมือไม่สำคัญ
  2. ซื้อสายรัดข้อมือเวลโคร
  3. ซื้อแบตเตอรี่แบบพกพา
  4. ซื้อ Sticky Velcro
  5. ใช้เข็มเย็บผ้า ติดสายรัดเวลโครเข้ากับฐานถุงมือ
  6. สายรัดข้อมือควรสามารถปรับให้เข้ากับขนาดข้อมือต่างๆ ได้
  7. ติดเทปกาวที่ฐานของมาตรความเร่งแล้วติดเข้ากับนิ้วชี้ของถุงมือ
  8. ติดเทปกาวที่ขนนกแล้วติดที่ด้านบนของถุงมือ
  9. การใช้สายไฟเชื่อมต่อพิน 3V3 ในขนนกเข้ากับพิน VIN ในมาตรความเร่ง
  10. การใช้สายไฟเชื่อมต่อพิน GND ในขนนกเข้ากับพิน GND ของมาตรความเร่ง
  11. การใช้สายไฟเชื่อมต่อพิน SCL ในขนนกเข้ากับพิน SCL ของมาตรความเร่ง
  12. การใช้สายไฟเชื่อมต่อพิน SDA ในขนนกเข้ากับพิน SDA ของมาตรความเร่ง
  13. เชื่อมต่อแบตเตอรี่อย่างน้อย 5 โวลต์ผ่าน usb เข้ากับขนนกเพื่อจ่ายไฟ

ขั้นตอนที่ 3: แม่เหล็ก

แม่เหล็ก
แม่เหล็ก

ขั้นตอนที่ 1: วางแม่เหล็กสองตัวที่มีกำลังเท่ากันตรงข้ามกัน

ขั้นตอนที่ 2: วัดช่องว่าง 30 ซม. ระหว่างแม่เหล็กสองตัว

ขั้นตอนที่ 3: วาง Magnetometer ตรงกลางของแม่เหล็กทั้งสองพอดี คุณควรได้รับข้อมูลประมาณ 0 ในขณะที่อยู่ตรงกลาง หากคุณได้รับการอ่านค่าศูนย์ให้ข้ามไปยังขั้นตอนที่ 5

ขั้นตอนที่ 4: หากค่าที่อ่านได้ไม่ใช่ศูนย์หรือใกล้กับศูนย์ คุณต้องปรับระยะห่างของแม่เหล็ก ถ้าค่าที่อ่านได้เป็นค่าลบ ให้เลื่อนแม่เหล็กด้านซ้ายออกเซนติเมตรหรือ 2 ไปทางซ้ายหรือจนกว่าค่าที่อ่านได้จะเป็นศูนย์ หากเป็นบวกให้ทำสิ่งเดียวกันยกเว้นแม่เหล็กที่ถูกต้อง

ขั้นตอนที่ 5: เขียนโค้ดที่รับข้อมูลจากเครื่องวัดความเข้มข้นของสนามแม่เหล็กและอ่านค่าว่าเป็นค่าบวกหรือค่าลบ ถ้าบวกมีรหัสให้ลากเส้นไปทางขวาและถ้าเป็นลบให้ลากเส้นไปทางซ้าย

ขั้นตอนที่ 4: รหัส

รหัส
รหัส

github.iu.edu/ise-e101-F17/MuscleMemory-Sw…

บทนำ:

ในการประมวลผลข้อมูลจากมาตรความเร่ง ต้องสร้างความสัมพันธ์ระหว่างไคลเอ็นต์/เซิร์ฟเวอร์ระหว่างขนนก Adafruit และเซิร์ฟเวอร์ที่ประมวลผลข้อมูล (ทำงานบนแล็ปท็อป/เดสก์ท็อป) ต้องสร้างไฟล์โค้ดสองไฟล์: ไฟล์หนึ่งสำหรับไคลเอนต์ (ขนนก Adafruit) และอีกไฟล์สำหรับเซิร์ฟเวอร์ (ในกรณีนี้คือแล็ปท็อปของ Jarod) ไคลเอนต์เขียนด้วย C ++ และเซิร์ฟเวอร์เขียนด้วย python ภาษาที่ใช้สำหรับลูกค้ามีความสำคัญเนื่องจาก Arduino เป็นภาษา C++ เป็นหลัก และการเปลี่ยนไปใช้ภาษาอื่นเป็นเรื่องยาก เซิร์ฟเวอร์สามารถเขียนเป็นภาษาใดก็ได้ ตราบใดที่มีคุณลักษณะเครือข่าย

การตั้งค่าไคลเอนต์:

ขั้นแรก เราจะตั้งค่ารหัสลูกค้า รหัสการเชื่อมต่อ WiFi ส่วนใหญ่พร้อมใช้งานผ่านห้องสมุด Adafruit เราเริ่มต้นด้วยการรวมชั้นเรียนที่เกี่ยวข้อง

#รวม #รวม #รวม #รวม #รวม

กำหนดตัวแปรบางอย่างที่จะใช้ตลอดทั้งโค้ด

// เชื่อมต่อกับเครือข่าย const char* ssid = "MMServer"; const char* password = "MMServer-รหัสผ่าน"; // IP และพอร์ตของเซิร์ฟเวอร์ที่จะรับข้อมูล const char* host = "149.160.251.3"; พอร์ต int const = 12347; บูลเชื่อมต่อ = เท็จ;

// เริ่มต้นตัวตรวจจับการเคลื่อนไหว

Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0 (1000);

ไคลเอนต์ WiFiClient;

สร้างฟังก์ชัน setup() ซึ่งจะทำงานทันทีที่ขนนกเริ่มทำงาน

// ตั้งค่าการเชื่อมต่อ WiFi และเชื่อมต่อกับการตั้งค่าเซิร์ฟเวอร์เป็นโมฆะ () { Serial.begin (9600); ล่าช้า (100);

Serial.println();

Serial.println(); Serial.print("กำลังเชื่อมต่อกับ "); Serial.println(ssid); // เริ่ม WiFi WiFi.begin (ssid, รหัสผ่าน); // กำลังเชื่อมต่อ… ในขณะที่ (WiFi.status () != WL_CONNECTED) { ล่าช้า (500); Serial.print("."); } // เชื่อมต่อกับ WiFi Serial.println(""); Serial.println ("เชื่อมต่อ WiFi"); Serial.println("ที่อยู่ IP:"); Serial.println(WiFi.localIP());

#ifndef ESP8266

ในขณะที่(!ซีเรียล); #endif Serial.begin(9600); Serial.println ("การทดสอบเซนเซอร์");

// เริ่มต้นเซ็นเซอร์

if(!lsm.begin()) { // มีปัญหาในการตรวจหา Serial.print LSM9DS0 (F("อ๊ะ ไม่พบ LSM9DS0 … ตรวจสอบการเดินสายของคุณหรือ I2C ADDR!")); ในขณะที่(1); } Serial.println(F("พบ LSM9DS0 9DOF")); // เริ่มเชื่อมต่อกับเซิร์ฟเวอร์ Serial.print("กำลังเชื่อมต่อกับ "); Serial.println (โฮสต์);

// ตรวจสอบการเชื่อมต่อสำเร็จ ถ้าล้มเหลวก็ยกเลิก

if (!client.connect (host, port)) { Serial.println ("การเชื่อมต่อล้มเหลว"); เชื่อมต่อ = เท็จ; กลับ; } อื่น ๆ { เชื่อมต่อ = จริง; }

//ตั้งค่าเกนเซ็นเซอร์และเวลารวม

กำหนดค่าเซ็นเซอร์ (); }

เราต้องการฟังก์ชันวนซ้ำที่จะวนซ้ำ ในกรณีนี้ จะใช้เพื่อส่งข้อมูลซ้ำๆ จากมาตรความเร่งไปยังเซิร์ฟเวอร์ในรูปแบบ "[z_accel]:[y_mag]:[z_mag]" client.print(ตัวเลข); ฟังก์ชั่นคือสิ่งที่ส่งข้อมูลไปยังเซิร์ฟเวอร์

วงเป็นโมฆะ () { ล่าช้า (250); if(connected){ // สิ่งนี้จะส่งข้อมูลไปยังเซิร์ฟเวอร์ sensors_event_t accel, mag, gyro, temp; lsm.getEvent(&เร่ง, &mag, &gyro, &temp); หมายเลขสตริง; ตัวเลข += accel.acceleration.z; ตัวเลข += ":"; ตัวเลข += mag.magnetic.y; ตัวเลข += ":"; ตัวเลข += mag.magnetic.z; Serial.print (ตัวเลข); client.print(ตัวเลข); Serial.println(); } อื่น ๆ { สร้างการเชื่อมต่อ (); } }

สำหรับฟังก์ชันยูทิลิตี้บางอย่าง เราจำเป็นต้องมีฟังก์ชันหนึ่งเพื่อสร้างการเชื่อมต่อระหว่างขนนกกับเซิร์ฟเวอร์

ถือเป็นโมฆะ createConnection(){ if (!client.connect(host, port)) { Serial.println("connection failed"); เชื่อมต่อ = เท็จ; กลับ; } อื่น ๆ { เชื่อมต่อ = จริง; } }

เรายังต้องกำหนดค่าเซ็นเซอร์และกำหนดช่วงของค่าที่จะอ่านได้ ตัวอย่างเช่น การเร่งความเร็วมี 5 ตัวเลือกสำหรับช่วง: 2g, 4g, 6g, 8g และ 16g

เป็นโมฆะ configurationSensor (เป็นโมฆะ) { // ตั้งค่าช่วงมาตรความเร่ง //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); // ตั้งค่าความไวของสนามแม่เหล็ก //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_2GAUSS); //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_4GAUSS); //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_8GAUSS); lsm.setupMag(lsm. LSM9DS0_MAGGAIN_12GAUSS);

// ตั้งค่าไจโรสโคป

lsm.setupGyro (lsm. LSM9DS0_GYROSCALE_245DPS); //lsm.setupGyro(lsm. LSM9DS0_GYROSCALE_500DPS); //lsm.setupGyro(lsm. LSM9DS0_GYROSCALE_2000DPS); }

การตั้งค่าเซิร์ฟเวอร์:

เซิร์ฟเวอร์จะเป็นไฟล์หลามที่จะทำงานบนบรรทัดคำสั่งของคอมพิวเตอร์ ในการเริ่มต้น ให้นำเข้าคลาสที่จำเป็น

นำเข้า socketimport นำเข้าใหม่ pyautogui

ซ็อกเก็ตใช้สำหรับเครือข่าย re ใช้สำหรับ regex หรือการจัดการสตริง pyautogui เป็นไลบรารี่ของ python ที่จะช่วยให้การวาดเกิดขึ้นได้ (จะกล่าวถึงในภายหลัง)

ต่อไป เราควรกำหนดตัวแปรบางตัว ตัวแปรเหล่านี้จะเป็นตัวแปรส่วนกลาง ดังนั้นจะเข้าถึงได้ในหลายฟังก์ชัน พวกเขาจะถูกใช้ในภายหลังในรหัส

ผม = 0n = 0 บรรทัด = 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 = เท็จ

first_data = True

ตอนนี้เราต้องการฟังก์ชันเพื่อสร้างเซิร์ฟเวอร์และเปิดสำหรับการเชื่อมต่อขาเข้า

def startServer (): global i global first_data # เริ่มต้นเซิร์ฟเวอร์ socket serversocket = socket.socket (socket. AF_INET, socket. SOCK_STREAM) serversocket.setsockopt (socket. SOL_SOCKET, socket. SO_REUSEADDR, 1) # Server IP address และ port host = " 149.160.251.3" พอร์ต = 12347 server_address = (โฮสต์, พอร์ต) # เปิดเซิร์ฟเวอร์และฟังการพิมพ์การเชื่อมต่อขาเข้า ('เซิร์ฟเวอร์เริ่มต้นบนพอร์ต %s %s' % server_address) serversocket.bind(server_address) serversocket.listen(5) # รอการเชื่อมต่อ… ในขณะที่ True: พิมพ์ ('กำลังรอการเชื่อมต่อ…') # ยอมรับการเชื่อมต่อขาเข้า (ไคลเอนต์ ที่อยู่) = serversocket.accept() # พยายามแยกวิเคราะห์ข้อมูลที่ได้รับ ลอง: พิมพ์ ('สร้างการเชื่อมต่อจาก ' ที่อยู่) ในขณะที่ True: # รับข้อมูลและส่งเพื่อประมวลผลข้อมูล = 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: movingAcce l(accel_data[0]) processData(accel_data) first_data = False ในที่สุด: # ปิดซ็อกเก็ตเพื่อป้องกันข้อมูลรั่วไหลที่ไม่จำเป็น

ตอนนี้เราต้องการฟังก์ชันที่จะประมวลผลข้อมูลทั้งหมด ขั้นตอนแรกที่ต้องทำและเรียกฟังก์ชันแรกคือการสอบเทียบเซ็นเซอร์เพื่อการคำนวณ

def calibData (รายการ): 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)

ต่อไป เราสร้างออฟเซ็ตการเร่งความเร็วเคลื่อนที่ ทำให้โปรแกรมรับรู้เมื่อมีคนหยุดขยับนิ้ว เนื่องจากค่าความเร่งทั้งหมดที่ส่งไปยังเซิร์ฟเวอร์ควรเหมือนกันในขณะนั้น

def movingAccel(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 or z_diff < -0.2): # ตรวจพบการเคลื่อนไหวภายในข้อมูล รีสตาร์ท keep_offset = True n = 0 z_calib = 0 z_moving_offset = 0 z_diff = 0 data_list = แตกถ้าไม่ keep_offset: # อยู่กับที่ในข้อมูล ตั้งค่าใหม่ z_offset z_offset = z_moving_offset print("New z_offset: ") print(z_offset) n = 0 z_cali = 0 z_moving_offset = 0 z_offset = 0 data_list] keep_offset = เท็จ keep_offset = เท็จ

ต่อไป เราทำหนักของคณิตศาสตร์ ซึ่งเกี่ยวข้องกับการแปลข้อมูลความเร่งเป็นข้อมูลตำแหน่งซึ่งจะทำให้เราสามารถบอกทิศทางที่ผู้ใช้ขยับนิ้วได้

def processData (รายการ): #[accel.z, mag.y] global z_offset global z_real global z_velo global z_pos global first_data ทั่วโลก mag_data

z_real = float(รายการ[0]) - z_offset

mag_y = รายการ[1] mag_z = รายการ[2] ซ้าย = เท็จ ขวา = เท็จ # อย่าประมวลผลการเร่งความเร็วจนกว่าจะแน่ใจว่าได้เร่งขึ้นแล้วจริงๆ # ป้องกันเสียงรบกวนจากกลไกไม่ให้ส่งผลต่อตำแหน่ง if(z_real -0.20): z_real = 0 #Begin การรวมเพื่อค้นหาตำแหน่ง 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) อื่นๆ: 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(right): movement(50, int(z_pos*) 1000)) elif(ซ้าย): การเคลื่อนไหว(-50, int(z_pos*1000)) z_velo = 0 z_pos = 0

ในที่สุด เราก็เลื่อนเคอร์เซอร์! ในการทำเช่นนี้ เราได้เปิดหน้าต่างระบายสีและทำให้เต็มหน้าจอ ไลบรารี pyautogui มีฟังก์ชันที่เรียกว่า pyautogui.dragRel(x, y); ซึ่งเราใช้ลากเคอร์เซอร์ของเมาส์จากจุดหนึ่งไปยังอีกจุดหนึ่ง ใช้ข้อมูลตำแหน่งสัมพัทธ์เพื่อให้การเคลื่อนไหวสัมพันธ์กับตำแหน่งสุดท้ายของเคอร์เซอร์

การเคลื่อนไหว def(x, y): print("ย้ายไปที่", x, -y) pyautogui.dragRel(x, -y)

สุดท้ายนี้ เราต้องเรียกใช้ฟังก์ชันหลักเพื่อให้โค้ดทั้งหมดนี้ทำงาน

# เรียกใช้ฟังก์ชันเพื่อเริ่มต้นเซิร์ฟเวอร์เริ่มต้นเซิร์ฟเวอร์ ()

แนะนำ: