สารบัญ:
- ขั้นตอนที่ 1: เซ็นเซอร์ IMU
- ขั้นตอนที่ 2: สิ่งต่าง ๆ ไม่สะอาด ง่ายเสมอไป
- ขั้นตอนที่ 3: การทดสอบเบื้องต้น
- ขั้นตอนที่ 4: การแก้ไขปัญหา
- ขั้นตอนที่ 5: การอ่านข้อมูลของเซ็นเซอร์
- ขั้นตอนที่ 6: มาขุดเพิ่มเติมในการอ่าน / Data
- ขั้นตอนที่ 7: เราสามารถส่งผลต่ออุณหภูมิและความเร่งได้
- ขั้นตอนที่ 8: มาตรความเร่งและไจโรสโคป
- ขั้นตอนที่ 9: (กำลังดำเนินการ) Magnetometer
วีดีโอ: Wallace - หุ่นยนต์อิสระ DIY - ตอนที่ 5 - เพิ่ม IMU: 9 ขั้นตอน
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:06
เรากำลังดำเนินการพร้อมกับวอลเลซ ชื่อ Wallace มาจากการผสมผสานของ "Wall-E" และจากโปรเจ็กต์ก่อนหน้า (การรู้จำเสียง) และในการใช้ยูทิลิตี้ "espeak" มันฟังดูค่อนข้างอังกฤษ และเหมือนคนรับใช้หรือพ่อบ้าน และนั่นคือเป้าหมายสุดท้าย: เพื่อให้โครงการนี้กลายเป็นสิ่งที่มีประโยชน์ ดังนั้น "วอลเลซ"
วอลเลซสามารถเคลื่อนที่ไปมาได้ เขาสามารถหลีกเลี่ยงสิ่งกีดขวางโดยใช้เซ็นเซอร์ระยะอินฟราเรด (เมื่อเร็ว ๆ นี้ แต่อย่างใดพวกเขาทอด (?) (ต้องดูให้ดีเมื่อมีโอกาส) ยังมีเซ็นเซอร์วัดระยะอะคูสติกบางตัว (สามตัวเสียพร้อมกัน ร่วมกับเครื่องขยายสัญญาณ MCP23017) และสุดท้ายสามารถตรวจจับการเปลี่ยนแปลงของกระแสมอเตอร์เพื่อทราบเมื่อชนกับบางสิ่ง
นอกจากเซ็นเซอร์แล้ว วอลเลซยัง "จำ" การเคลื่อนไหวทั้ง 100 การเคลื่อนไหวได้ และมีการวิเคราะห์เบื้องต้นโดยใช้ประวัติการเคลื่อนไหว
เป้าหมายจนถึงตอนนี้สำหรับ Wallace คือพยายามเดินหน้าต่อไป และรู้ว่าเมื่อใดที่มันติดอยู่กับรูปแบบที่ซ้ำซากจำเจ (เช่น ในมุมหนึ่ง) และไม่ได้ก้าวไปข้างหน้าจริงๆ
ฉันได้ทำซ้ำหลายครั้งสำหรับการเคลื่อนไหวและการนำทาง และอาการปวดหัวที่สม่ำเสมอเกิดขึ้นระหว่างการหมุน
เนื่องจากวอลเลซเป็นหุ่นยนต์ติดตาม และฉันต้องการทำให้ทุกอย่างง่ายขึ้นในซอฟต์แวร์ (สำหรับภายหลัง) เพื่อที่จะเปลี่ยน ฉันแค่ให้เขาหมุน/หมุนให้เข้าที่ ดังนั้นให้ใช้กำลัง / รอบการทำงานเท่ากัน แต่ตรงกันข้ามกับมอเตอร์
ปัญหาที่พบเกิดจากการออกแบบแพลตฟอร์มหุ่นยนต์ Agent 390 สายพานแทร็กมักจะเสียดสีกับด้านข้าง และที่แย่กว่านั้น ฝ่ายหนึ่งทำมากกว่าอีกฝ่าย
บนพื้นและทางตรงก็ไม่มีปัญหา ปรากฏบนพรม ฉันเลือกที่จะไม่ให้วอลเลซอยู่บนพื้นพรมหลังจากที่พรมมีคราบสกปรก
ปัญหาที่แท้จริงคือเมื่อหมุนบนพื้น
หากฉันมีซอฟต์แวร์ที่ใช้รอบการทำงานระดับสูง ซอฟต์แวร์ก็จะเปลี่ยนอย่างสม่ำเสมอไม่มากก็น้อย อย่างไรก็ตาม ในระหว่างรอบการทำงานต่ำ เครื่องอาจหมุนหรือไม่หมุนก็ได้ หรืออาจจะหมุนไปซักพักแล้วก็ช้าลง การดำเนินการหมุนกลับดูเหมือนจะควบคุมไม่ได้ผ่านทางซอฟต์แวร์ หรืออย่างดีที่สุดก็ทำได้ยากมาก
ปัญหาจะปรากฏขึ้นระหว่างการนำทางและเคลื่อนที่ไปรอบๆ หรืออยู่ห่างจากสิ่งกีดขวาง มันสามารถแกว่งไปมาอย่างดุเดือดเกินไป หรือมันอาจติดขัดเมื่อพยายามเปลี่ยนกะทีละน้อยโดยไม่ได้ขยับเลย
ดังนั้นคำอธิบายข้างต้นจึงกระตุ้นคำแนะนำนี้
ตอนแรกฉันต้องการจะแจกจ่ายหรือล่าช้าในการแนะนำหน่วยตรวจจับการเคลื่อนไหว (IMU) เพราะพวกเขา A) ซับซ้อน B) เสียงดัง C) ข้อผิดพลาดสามารถเกิดขึ้นได้เมื่อเวลาผ่านไปและอื่น ๆ ฯลฯ ความคิดของฉันมี โดยที่เราสามารถทำได้ดีมากโดยการก้าวไปข้างหน้ากับเซ็นเซอร์เลเซอร์ IR ในช่วงเวลาของเที่ยวบิน และเราทำได้ โดยใช้เลเซอร์ เราสามารถรู้ได้ว่าหุ่นยนต์หมุนหรือไม่ โดยการติดตามการเปลี่ยนแปลงของระยะทาง
อันที่จริง เราสามารถ (ประมาณ) ทำเช่นนั้นได้ด้วยเซ็นเซอร์เสียง
อย่างไรก็ตาม ทั้งหมดนั้นเป็นวิธีที่อ้อมและซับซ้อนมากในการตอบคำถามง่ายๆ เพียงข้อเดียว: "เราหมุนเวียนไปแล้วหรือไม่"
สำหรับฉัน ดูเหมือนว่าการกระโดดไปใช้เซ็นเซอร์เลเซอร์ ToF จะนำฉันไปสู่ซอฟต์แวร์อีกระดับ กล่าวคือ SLAM (การโลคัลไลเซชันและการทำแผนที่พร้อมกัน) ฉันยังไม่พร้อมที่จะไปที่นั่น
เป็นสิ่งที่ดีที่จะทำโปรเจ็กต์หุ่นยนต์ในเลเยอร์ โดยที่เลเยอร์แรก (ล่าง) จะง่ายกว่า และเลเยอร์หลัง (บน) เป็นนามธรรมมากกว่าและจัดการกับปัญหาที่ยากขึ้น
เลเยอร์สามารถคิดได้ดังนี้:
- กรอบทางกายภาพของหุ่นยนต์ / พื้นฐานโครงสร้างทางกล
- ระบบขับเคลื่อนพื้นฐาน (ราสเบอร์รี่, โรโบคลอว์, มอเตอร์, สายเคเบิล, ฯลฯ, ซอฟต์แวร์พื้นฐาน, ขับเคลื่อนด้วยคีย์บอร์ด)
- วงจรที่จำเป็นเพื่อรองรับเซ็นเซอร์ (ตัวเปลี่ยนแรงดันไฟฟ้าแบบสองทิศทาง, ตัวขยายพอร์ต, E-Stop, การกระจายกำลัง ฯลฯ)
- เซ็นเซอร์หลีกเลี่ยงสิ่งกีดขวาง (อะคูสติก, IR)
- การตรวจจับตำแหน่งและการเคลื่อนไหวขั้นพื้นฐานที่จำเป็น (มาตรความเร่ง, ไจโร, เครื่องวัดความเข้มข้นของสนามแม่เหล็ก, เครื่องเข้ารหัสมอเตอร์, เครื่องเข้ารหัสล้อ)
คุณสามารถสร้างรายการของคุณเองได้ ประเด็นเกี่ยวกับรายการนี้คือ คุณควรทำสิ่งเหล่านี้มากหรือน้อยตามลำดับนั้น และถ้าคุณใช้เวลาพอสมควรในแต่ละเลเยอร์เพื่อให้แต่ละเลเยอร์มีสถานะการทำงานที่ดี สิ่งนี้จะช่วยคุณได้ในภายหลังเมื่อสิ่งต่างๆ ซับซ้อนขึ้น
รายการด้านบนอาจจับคู่กับเลเยอร์แนวคิดเหล่านี้ในซอฟต์แวร์ไม่มากก็น้อย
- SLAM (การโลคัลไลเซชันและการทำแผนที่พร้อมกัน)
- การควบคุมและการรับรู้การเคลื่อนไหว การหมุน
- การหลีกเลี่ยงอุปสรรคพื้นฐาน
- การควบคุมและตรวจจับข้อมูลเซ็นเซอร์
- การเคลื่อนไหวที่สำคัญ เดินหน้า ถอยหลัง ซ้ายและขวา เร่งความเร็ว ช้าลง หยุด
อย่างที่คุณเห็น สำหรับรายการนี้ รายการแรกจะเป็นเลเยอร์ด้านบนและซับซ้อนกว่า ซึ่งจะจัดการกับปัญหาและคำถามที่เป็นนามธรรมมากขึ้น เช่น "ฉันอยู่ที่ไหน" และ "ฉันกำลังจะไปไหน" ในขณะที่รายการหลังจะเป็น เลเยอร์ซอฟต์แวร์ที่ต่ำกว่าซึ่งจัดการ "วิธีพูด/ฟังเซ็นเซอร์ A" หรือ "วิธีขยับวงล้อนี้"
ฉันไม่ได้บอกว่าเมื่อคุณเริ่มที่เลเยอร์ คุณจะทำเสร็จแล้วในเลเยอร์ถัดไป จะไม่กลับไปที่เลเยอร์ก่อนหน้า โครงการหุ่นยนต์อาจคล้ายกับวิธีการพัฒนาซอฟต์แวร์แบบวนซ้ำสมัยใหม่ (agile, SCRUM เป็นต้น)
ฉันแค่บอกว่าจะใช้เวลาในแต่ละครั้ง คุณจะต้องสร้างสมดุลว่าจะทำอย่างไรในแต่ละครั้ง และตัดสินใจว่าคุณกำลังพยายามทำอะไรในชั้นหนึ่งซึ่งคุ้มค่ากับเวลาและปัญหา
มี "ความขัดแย้ง" หรือ "ความตึงเครียด" บางอย่างระหว่างสองแนวคิดหรือทิศทางที่แข่งขันกัน
สิ่งหนึ่งที่ฉันจะเรียกว่า "plug-n-play" เพื่อแก้ปัญหา A.
อีกอย่างคือ DIY (ทำเอง) และนั่นอาจไม่ใช่ฉลากที่ดีที่สุดสำหรับแนวคิดอื่นนี้ด้วยซ้ำ
นี่คือตัวอย่างของแต่ละตัวเลือก หวังว่าคุณจะเห็นความตึงเครียดหรือความขัดแย้งระหว่างสองตัวเลือกนี้
สำหรับตัวอย่างนี้ ให้รวม SLAM การหลีกเลี่ยงสิ่งกีดขวาง และการเคลื่อนไหวพื้นฐานที่จำเป็นทั้งหมดเป็นปัญหาเดียวที่ต้องแก้ไขพร้อมกัน
- หากเราตัดสินใจที่จะใช้เส้นทาง Plug-n-play เราจะกระโดดทันที (ขึ้นอยู่กับงบประมาณ) ไปยังสิ่งต่างๆ เช่น เลเซอร์แบบหมุนได้ด้านบน หรือกล้องระยะชัดลึก หรือเลเซอร์ ToF และ IMU (หัวข้อของเรื่องนี้) สอนได้)
- ในทางกลับกัน หากเราต้องการไปยังเส้นทางที่สอง เราอาจพยายามดึงข้อมูลทุกบิตที่เป็นไปได้ออกจากเซ็นเซอร์เสียงหรือเซ็นเซอร์ IR บางตัว หรือไม่มีเซ็นเซอร์เลย - เราแค่ใช้การตรวจสอบกระแสมอเตอร์ (bump)
สิ่งที่สามารถพูดเกี่ยวกับ #1 vs #2? สิ่งหนึ่งที่เราจะได้เรียนรู้มากขึ้นจากการทำ #2 ข้อจำกัดของการมีเพียงเซ็นเซอร์เสียงเท่านั้นที่ใช้งานได้ ทำให้เราต้องคิดถึงปัญหาอีกมากมาย
ในทางกลับกัน หากเราจดจ่อกับการทำสิ่งต่าง ๆ ผ่าน #2 มากเกินไป เราอาจเสียเวลาเพราะเราขอมากกว่าที่ควรจากเซ็นเซอร์เสียง
อีกหนึ่งแนวคิดหรือแนวคิดที่ควรคำนึงถึง: ส่วนผสมของฮาร์ดแวร์และซอฟต์แวร์ชนิดใดที่ตอบโจทย์ "วิธีการ" ได้ดีที่สุด และส่วนผสมของซอฟต์แวร์ (และฮาร์ดแวร์) ชนิดใดที่ตอบคำถามว่า "อะไร" "เมื่อไหร่" "ที่ไหน". เนื่องจาก "วิธีการ" มักจะเป็นคำถามระดับล่างซึ่งขึ้นอยู่กับ "อะไร" "เมื่อไหร่" และ "ที่ไหน" เพื่อให้ได้คำตอบ
อย่างไรก็ตาม ทั้งหมดข้างต้นเป็นเพียงสิ่งที่ต้องคิด
ในกรณีของฉัน หลังจากใช้ความพยายามอย่างมากและมีปัญหาเรื่องแรงเสียดทานของแทร็กที่น่ารำคาญอย่างต่อเนื่อง และไม่สามารถควบคุมและเคลื่อนไหวได้อย่างสม่ำเสมอ ถึงเวลาต้องทำอย่างอื่นแล้ว
ดังนั้นคำแนะนำนี้ - IMU
เป้าหมายคือถ้า IMU บอกว่าหุ่นยนต์ไม่หมุน เราจะเพิ่มรอบการทำงาน หากเราหมุนเร็วเกินไป เราจะลดรอบการทำงานลง
ขั้นตอนที่ 1: เซ็นเซอร์ IMU
ดังนั้นเซ็นเซอร์ตัวต่อไปของเราที่จะเพิ่มลงใน Wallace คือ IMU หลังจากการค้นคว้า ฉันกำลังตัดสินใจใช้ MPU6050 แต่ในเวลานี้ MPU9050 (และล่าสุดคือ MPU9250) ดูเหมือนจะเป็นแนวคิดที่ดียิ่งขึ้นไปอีก
แหล่งที่มาของฉันคือ Amazon (ในสหรัฐอเมริกา) เลยสั่งมาสองตัว
สิ่งที่ฉันได้รับ (ดูเหมือนว่าจะควบคุมสิ่งนี้ไม่ได้ นั่นคือสิ่งที่ฉันไม่ชอบเกี่ยวกับ Amazon) คือ MPU92/65 สองตัว ฉันสงสัยเล็กน้อยเกี่ยวกับการกำหนด ดูภาพ; ที่ดูเหมือนจะเป็นการกำหนด "ครอบครัว" ไม่ว่าในกรณีใดนั่นคือสิ่งที่ฉันติดอยู่
การเพิ่มมันง่ายมาก - รับโปรโตบอร์ดพร้อมรางเชื่อมต่อ ประสานเซ็นเซอร์กับบอร์ด เพิ่มขั้วต่อสกรู 10 พิน (ฉันได้ของฉันจาก Pololu)
เพื่อลดการรบกวน ฉันพยายามวางเซ็นเซอร์เหล่านี้ให้ห่างจากสิ่งอื่น
นั่นหมายถึงการใช้น็อต/น็อตไนลอนด้วย
ฉันจะใช้โปรโตคอล I2C หวังว่าความยาวสายไฟทั้งหมดจะไม่เลวร้ายเกินไป
มีข้อมูลมากมายที่อื่นเกี่ยวกับการเชื่อมต่อพื้นฐานและระดับแรงดันไฟฟ้า ฯลฯ ดังนั้นฉันจะไม่ทำซ้ำที่นี่
ขั้นตอนที่ 2: สิ่งต่าง ๆ ไม่สะอาด ง่ายเสมอไป
ในการเขียนนี้ ดูเหมือนจะไม่ค่อยมีอะไรออนไลน์มากนักสำหรับ MPU-92/65 นี้โดยเฉพาะ สิ่งที่มีอยู่ เหมือนกับเซ็นเซอร์ส่วนใหญ่ ดูเหมือนจะเป็นตัวอย่างการใช้ Arduino
ฉันพยายามทำให้ Instructables เหล่านี้แตกต่างออกไปเล็กน้อยโดยนำเสนอกระบวนการที่ไม่สะอาด เพราะสิ่งต่างๆ ไม่ได้ผลในทันที
ฉันคิดว่าคำแนะนำเหล่านี้คล้ายกับบล็อกมากกว่า A-B-C แบบตรง 1-2-3 "นี่คือวิธีที่คุณทำ"
ขั้นตอนที่ 3: การทดสอบเบื้องต้น
จากภาพในขั้นตอนที่แล้ว สายไฟสีแดงและสีดำที่ไปยังเซ็นเซอร์คือ VCC (5V) และ GND สายสีเขียวและสีเหลืองคือการเชื่อมต่อ I2C
หากคุณทำโปรเจ็กต์ I2C อื่นๆ หรือติดตามซีรีส์เหล่านี้ คุณก็รู้เกี่ยวกับ "i2cdetect" แล้ว และนั่นเป็นขั้นตอนแรกที่จะทราบว่า Raspberry สามารถมองเห็นเซ็นเซอร์ใหม่ได้หรือไม่
ดังที่คุณเห็นจากรูปภาพในขั้นตอนนี้ ความพยายามครั้งแรกของเราไม่สำเร็จ IMU ไม่ปรากฏขึ้น (ควรเป็นรหัสอุปกรณ์ 0x68)
อย่างไรก็ตาม ข่าวดีก็คือว่าบัส I2C กำลังทำงานอยู่ เราเห็นหนึ่งอุปกรณ์ 0x20 และมันคือตัวขยายพอร์ต MCP23017 (ปัจจุบันรับผิดชอบเซ็นเซอร์เสียง HCSR04)
ในภาพเห็นไม่ง่ายนัก แต่ฉันเชื่อมต่อสายสีเขียวและสีเหลืองสีเดียวกันจาก IMU เข้ากับ MCP23017 (ดูด้านล่างซ้ายในรูปภาพ)
เราจะต้องทำการแก้ไขปัญหาบางอย่าง
ขั้นตอนที่ 4: การแก้ไขปัญหา
โดยใช้การตั้งค่าความต่อเนื่องของโวลต์มิเตอร์ (แบบที่มีโทนเสียงสูง) ฉันทดสอบการเชื่อมต่อ VCC(5V), GND, SDA และ SCL นั่นเป็นสิ่งที่ดี
ความพยายามต่อไปคือการถอด MCP23017 ออกจากบัส I2C โดยเหลือเพียง MPU-92/65 บนบัสเท่านั้น ที่พิสูจน์แล้วว่าไร้ผล - "i2cdetect" ไม่พบอุปกรณ์ใดๆ
ต่อไป ฉันถอดเซ็นเซอร์ออกจากเสาโทเท็ม แล้วเดินสายใหม่ตรงไปยังบัสแบบสองทิศทาง 5V-to-3V กล่าวคือตรงไปที่ราสเบอร์รี่ (สายสั้น?).
และว้าว ครั้งนี้มีความสำเร็จ เราเห็น 0x68 ปรากฏขึ้นโดยใช้ "i2cdetect"
แต่เราไม่รู้ว่าทำไมครั้งนี้ถึงได้ผล อาจจะเป็นความยาวของสายไฟ? สถานที่ก่อนหน้านี้?
หมายเหตุ: ไม่ได้สร้างความแตกต่างไม่ว่า ADO จะต่อสายดินหรือไม่ก็ตาม อาจมีตัวต้านทานแบบดึงขึ้นและแบบดึงลงออนบอร์ด เช่นเดียวกันกับ FSYNC
ต่อไป ฉันเชื่อมต่อ MCP23017 อีกครั้ง ตอนนี้เรามีอุปกรณ์สองเครื่องบนบัส I2C (ดูภาพ). สำเร็จ ตอนนี้เราเห็นทั้ง 0x20 และ 0x68 ด้วย i2cdetect
วิดีโอกล่าวถึงสิ่งที่เกิดขึ้นระหว่างการแก้ไขปัญหาเพิ่มเติมเล็กน้อย
ขั้นตอนที่ 5: การอ่านข้อมูลของเซ็นเซอร์
แนวทางต่างๆ
ฉันตัดสินใจใช้หลายวิธีในการรับข้อมูลที่เป็นประโยชน์จากเซ็นเซอร์ สิ่งเหล่านี้ไม่ได้เรียงตามลำดับใด ๆ:
- ลองเขียนโปรแกรมพื้นฐานบ้าง
- ดูเอกสารออนไลน์เกี่ยวกับการลงทะเบียน
- ดูตัวอย่างและ / หรือโค้ดของผู้อื่น
ทำไมแนวทางเหล่านี้? ทำไมไม่ลองมองหาไลบรารี่หรือโค้ดที่มีอยู่ล่ะ?
ด้วยการทดลองและลองใช้แนวคิดบางอย่าง เราสามารถซึมซับความรู้บางอย่างเกี่ยวกับเซ็นเซอร์นี้ไม่เพียงเท่านั้น แต่ยังได้รับเทคนิค ทักษะ และวิธีการคิดเกี่ยวกับการแก้ปัญหาสิ่งใหม่ๆ และบางสิ่งที่อาจมีเอกสารไม่มาก สิ่งที่อาจมีจำนวนมากของสิ่งที่ไม่รู้จัก
นอกจากนี้ เมื่อเราได้เล่นและลองใช้แนวคิดของเราเองและได้รับข้อมูลเชิงลึกแล้ว เราก็อยู่ในตำแหน่งที่ดีกว่าในการประเมินโค้ดหรือไลบรารีของผู้อื่น
ตัวอย่างเช่น หลังจากดูโค้ด C++ สำหรับ MPU9250 ใน github แล้ว ฉันก็รู้ว่ามันบังคับให้ฉันใช้การขัดจังหวะ ซึ่งฉันยังไม่อยากทำ
นอกจากนี้ยังมาพร้อมกับสิ่งพิเศษเช่นการสอบเทียบ อีกครั้งที่ฉันยังไม่ได้สนใจ
อาจเป็นไปได้ว่าสิ่งที่ฉันต้องทำเพื่อตอบคำถามง่ายๆ "คือหุ่นยนต์หมุนใช่หรือไม่ใช่" สามารถตอบได้ง่ายๆเพียงแค่อ่านการลงทะเบียนบางส่วน
ทะเบียน
ในการเขียนนี้ ดูเหมือนว่าจะไม่มีเซ็นเซอร์นี้มากนัก อันที่จริงแล้ว หากคุณดูภาพที่มาพร้อมกับคำแนะนำนี้ และดูจารึกบนชิปจริงอย่างละเอียด มันทำให้ฉันสงสัยว่านี่ไม่ใช่การล้มเลิกความตั้งใจหรือไม่ ฉันไม่ได้เกี่ยวข้องกับสิ่งที่ฉันเห็นจาก Invense ไม่ว่าฉันจะเลือกดูข้อมูลการลงทะเบียนสำหรับรุ่นที่ฉันพบ: MPU-6050 และ MPU-9250
ในทั้งสองกรณี สิ่งต่อไปนี้จะเหมือนกันสำหรับทั้งสอง และสำหรับผู้เริ่มต้น เราคิดว่ามันจะเหมือนกันสำหรับ MPU-92/65 นี้ด้วย
59 ถึง 64 - การวัดความเร่ง
65, 66 - การวัดอุณหภูมิ 67 ถึง 72 - การวัดไจโรสโคป 73 ถึง 96 - ข้อมูลเซ็นเซอร์ภายนอก
ข้อควรทราบ: MPU-6050 ดูเหมือนจะไม่มีเครื่องวัดความเข้มข้นของสนามแม่เหล็ก ในขณะที่ MPU-9250 (และเราคิดว่าอันนี้ด้วย) ก็ไม่มี
ข้อมูลที่น่าสนใจและหวังว่าจะเป็นประโยชน์บางอย่างที่รวบรวมได้จากเอกสารการลงทะเบียน:
ข้อมูล Magnetometer:
magnetometer id: 0x48 register 00 ถึง 09: 00H WIA 0 1 0 0 1 0 0 0 01H INFO INFO7 INFO6 INFO5 INFO4 INFO3 INFO2 INFO1 INFO0 02H ST1 0 0 0 0 0 0 DOR DRDY 03H HXL HX7 HX6 HX5 HX4 HX3 HX02 HH1 HXH HX15 HX14 HX13 HX12 HX11 HX10 HX9 HX8 05H HYL HY7 HY6 HY5 HY4 HY3 HY2 HY1 HY0 06H HYH HY15 HY14 HY13 HY12 HY11 HY10 HY9 HY8 07H HZL HZ5 HZ7 HZ6 HZ6 HZ6 HZ6 HZ6 ST2 0 0 0 BITM HOFL 0 0 0 รายละเอียดของความหมายของแต่ละรีจิสเตอร์: HXL[7:0]: ข้อมูลการวัดแกน X ต่ำกว่า 8 บิต HXH[15:8]: ข้อมูลการวัดแกน X สูงกว่า HYL 8 บิต[7:0]: ข้อมูลการวัดแกน Y ต่ำกว่า 8 บิต HYH[15:8]: ข้อมูลการวัดแกน Y สูงขึ้น 8 บิต HZL[7:0]: ข้อมูลการวัดแกน Z ต่ำกว่า 8 บิต HZH[15:8]: ข้อมูลการวัดแกน Z สูงขึ้น 8bit
การเขียนโปรแกรม
ข้อมูลอีกเล็กน้อยจากเอกสารการลงทะเบียนคือดูเหมือนว่าจะมีการลงทะเบียนประมาณ 100 รายการเท่านั้น ดังนั้น กลวิธีหนึ่งอาจเป็นการเขียนโปรแกรมง่ายๆ ที่เข้าถึงอุปกรณ์ (0x68) และพยายามอ่านชุดของการลงทะเบียนตามลำดับโดยไม่คำนึงถึงความหมายของมัน เพียงเพื่อดูว่าข้อมูลใดบ้างที่สามารถเห็นได้
จากนั้น ทำการส่งผ่านแบบต่อเนื่อง โดยใช้รหัสเดียวกัน และเปรียบเทียบข้อมูลจากหนึ่งผ่านกับถัดไป
แนวคิดก็คือเราอาจกำจัดรีจิสเตอร์ที่ดูเหมือนไม่มีข้อมูล (ศูนย์หรือ FF ?) หรือที่ไม่มีวันเปลี่ยนแปลงได้เลย และเราสามารถมุ่งเน้นไปที่รีจิสเตอร์ที่เปลี่ยนแปลงได้
จากนั้น เรากำลังดูเฉพาะตัวที่เปลี่ยนแปลง เพิ่มในฟังก์ชันการเฉลี่ยที่หาค่าเฉลี่ยการอ่าน N ล่าสุดของรีจิสเตอร์นั้น เพื่อดูว่าในความเป็นจริงแล้วค่าคงที่ที่แน่นอนสำหรับรีจิสเตอร์นั้นหรือไม่ นี่จะถือว่าเรากำลังรักษาเซ็นเซอร์ให้นิ่งและอยู่ในตำแหน่งเดียวกัน
สุดท้าย เราสามารถลองใช้เซนเซอร์ต่างๆ อย่างนุ่มนวล เช่น สะกิด (มาตรความเร่ง ไจโร) หรือเป่า (อุณหภูมิ) หรือหมุน (สองตัวก่อนหน้าบวกแมกนิโตมิเตอร์) และดูว่าสิ่งนี้มีผลกระทบต่อค่าอย่างไร
ฉันชอบใช้ไลบรารี wiringPi ให้มากที่สุด รองรับ I2C
วิ่งครั้งแรก:
/********************************************************************************
* เพื่อสร้าง: gcc first.test.mpu9265.c -o first.test.mpu9265 -lwiringPi * * เพื่อเรียกใช้: sudo./first.test.mpu9265 * * โปรแกรมนี้เพิ่งส่งออกช่วงของการลงทะเบียน (ที่เป็นไปได้) จาก MCP23017, * และจาก MPU9265 (หรือ MPU อื่นใดที่ที่อยู่ 0x68 นั้น) * * ฉันใช้มันเพื่อตรวจสอบว่าฉันสามารถอ่านจากเซ็นเซอร์ได้หรือไม่ เนื่องจากฉัน * มีความมั่นใจใน MCP23017 แล้ว * ******************************************************* **********************************/ #include #include #include #include #int main (int argc, char** argv) { puts("มาดูกันว่า MCP23017 @ 0x20 พูดอะไร:"); เออร์โน = 0; int deviceId1 = 0x20; int fd1 = การเดินสายPiI2CSetup (deviceId1); ถ้า (-1 == fd1) { fprintf (stderr, "ไม่สามารถเปิดอุปกรณ์เดินสายPi I2C: %s\n", strerror (errno)); ส่งคืน 1; } สำหรับ (int reg=0;reg<300;reg++) { fprintf(stderr, "%d", wiringPiI2CReadReg8(fd1, reg));fflush(stderr); ล่าช้า(10); } ทำให้ (""); puts("มาดูกันว่า MPU9265 @ 0x20 พูดอะไร:"); เออร์โน = 0; int deviceId2 = 0x68; int fd2 = การเดินสายPiI2CSetup (deviceId2); ถ้า (-1 == fd2) { fprintf (stderr, "ไม่สามารถเปิดอุปกรณ์เดินสายPi I2C: %s\n", strerror (errno)); ส่งคืน 1; } สำหรับ (int reg=0;reg<300;reg++) { fprintf(stderr, "%d ", wiringPiI2CReadReg8(fd2, reg));fflush(stderr); ล่าช้า(10); } ทำให้ (""); กลับ 0; }
วิ่งครั้งที่สอง:
/********************************************************************************
* เพื่อสร้าง: gcc second.test.mpu9265.c -o second.test.mpu9265 -lwiringPi * * เพื่อเรียกใช้: sudo./second.test.mpu9265 * * โปรแกรมนี้แสดงหมายเลขลงทะเบียนพร้อมกับค่าที่อ่าน * * สิ่งนี้ทำให้มีประโยชน์ในการไพพ์ (เปลี่ยนเส้นทาง) เอาต์พุตไปยังไฟล์ จากนั้น * สามารถทำการเปรียบเทียบได้หลายรายการ อาจให้ข้อมูลเชิงลึกเกี่ยวกับ * การลงทะเบียนมีความสำคัญอย่างไรและข้อมูลอาจมีพฤติกรรมอย่างไร * ******************************************************* **********************************/ #include #include #include #include #include #int main (int argc, ถ่าน** argv) { int deviceId = -1; if (0) { } else if (!strncmp(argv [1], "0x20", strlen("0x20"))) { deviceId = 0x20; } else if (!strncmp(argv[1], "0x68", strlen("0x68"))) { deviceId = 0x68; } else if (!strncmp(argv[1], "0x69", strlen("0x69"))) { deviceId = 0x69; } puts("มาดูกันว่า MPU9265 @ 0x20 พูดอะไร:"); เออร์โน = 0; int fd = การเดินสายPiI2CSetup(deviceId); ถ้า (-1 == fd) { fprintf (stderr, "ไม่สามารถเปิดอุปกรณ์ WiringPi I2C: %s\n", strerror (errno)); ส่งคืน 1; } สำหรับ (int reg=0;reg<300;reg++) { fprintf(stderr, "%d:%d\n", reg, wiringPiI2CReadReg8(fd, reg));fflush(stderr); ล่าช้า(10); } คืนค่า 0; }
วิ่งที่สาม:
/********************************************************************************
* เพื่อสร้าง: gcc third.test.mpu9265.c -o third.test.mpu9265 -lwiringPi * * เพื่อเรียกใช้: sudo./third.test.mpu9265 * * โปรแกรมนี้เป็นผลจากโปรแกรมที่สอง มันอ่านเฉพาะจากการลงทะเบียน * ที่ระบุความแตกต่างระหว่างการรันหนึ่งครั้งและการรันครั้งถัดไป* ******************************************************* **********************************/ #include #include #include #include #include #int main (int argc, ถ่าน** argv) { int deviceId = -1; if (0) { } else if (!strncmp(argv [1], "0x68", strlen("0x68"))) { deviceId = 0x68; } else if (!strncmp(argv[1], "0x69", strlen("0x69"))) { deviceId = 0x69; } puts("มาดูกันว่า MPU9265 @ 0x20 พูดอะไร:"); เออร์โน = 0; int fd = การเดินสายPiI2CSetup(deviceId); ถ้า (-1 == fd) { fprintf (stderr, "ไม่สามารถเปิดอุปกรณ์ WiringPi I2C: %s\n", strerror (errno)); ส่งคืน 1; } สำหรับ (int reg=61;reg<=73;reg++) { fprintf(stderr, "%d:%d\n", reg, wiringPiI2CReadReg8(fd, reg));fflush(stderr); ล่าช้า(10); } สำหรับ (int reg=111;reg<=112;reg++) { fprintf(stderr, "%d:%d\n", reg, wiringPiI2CReadReg8(fd, reg));fflush(stderr); ล่าช้า(10); } สำหรับ (int reg=189;reg<=201;reg++) { fprintf(stderr, "%d:%d\n", reg, wiringPiI2CReadReg8(fd, reg));fflush(stderr); ล่าช้า(10); } สำหรับ (int reg=239;reg<=240;reg++) { fprintf(stderr, "%d:%d\n", reg, wiringPiI2CReadReg8(fd, reg));fflush(stderr); ล่าช้า(10); } คืนค่า 0; }
แล้วเราเรียนรู้อะไรมาบ้าง? รูปภาพของตารางที่มีพื้นที่เน้นสีแสดงว่าผลลัพธ์ดูเหมือนว่าจะตรงกับการลงทะเบียนชุดแรก
ผลลัพธ์ที่ได้สามารถสร้างคำถามใหม่ได้
คำถาม: เหตุใดจึงมีผลการลงทะเบียนเพียงรายการเดียวสำหรับกลุ่ม "ภายนอก"
คำถาม: อะไรคือการลงทะเบียนที่ไม่รู้จักทั้งหมด "??????"
คำถาม: เนื่องจากโปรแกรมไม่ได้ขับเคลื่อนด้วยอินเตอร์รัปต์ จึงขอข้อมูลช้าเกินไปหรือไม่ เร็วเกินไป?
คำถาม: เราสามารถส่งผลต่อผลลัพธ์โดยลองสิ่งต่างๆ กับเซ็นเซอร์ขณะทำงานได้หรือไม่
ขั้นตอนที่ 6: มาขุดเพิ่มเติมในการอ่าน / Data
ฉันคิดว่าขั้นตอนต่อไปก่อนสิ่งอื่นใดคือการปรับปรุงโปรแกรมเพื่อ:
- มีความยืดหยุ่นในความล่าช้าของลูป (ms)
- มีความยืดหยุ่นในการอ่านจำนวนครั้งเพื่อให้มีค่าเฉลี่ยการทำงานต่อการลงทะเบียน
(ฉันต้องแนบโปรแกรมเป็นไฟล์ ดูเหมือนว่าจะมีปัญหาในการแทรกที่นี่ "fourth.test.mpu9265.c")
นี่คือการวิ่งโดยใช้การอ่าน 10 ครั้งล่าสุดสำหรับค่าเฉลี่ย ที่ลูป 10ms:
sudo./fourth.test.mpu9265 0x68 10 10
61:255 0 255 0 255 0 255 0 0 0: 102 62:204 112 140 164 148 156 188 248 88 228: 167 63:189 188 189 187 189 188 188 188 188 189: 188 64: 60 40 16 96 208 132 116 252 172 36: 112 65: 7 7 7 7 7 7 7 7 7 7: 7 66:224 224 224 240 160 208 224 208 144 96: 195 67: 0 0 0 0 0 0 0 0 0 0: 0 68:215 228 226 228 203 221 239 208 214 187: 216 69: 0 255 0 255 255 0 255 0 0 0: 102 70:242 43 253 239 239 45 206 28 247 207: 174 71: 0 255 255 0 255 255 255 255 255 255: 204 72: 51 199 19 214 11 223 21 236 193 8: 117 73: 0 0 0 0 0 0 0 0 0 0: 0 111: 46 149 91 199 215 46 142 2 233 199: 132 112: 0 0 0 0 0 0 0 0 0 0: 0 189:255 0 255 0 255 0 0 255 0 255: 127 190: 76 36 240 36 100 0 164 164 152 244: 121 191:188 188 188 188 187 188 187 189 187 189: 187 192: 8 48 48 196 96 220 144 0 76 40: 87 193: 7 7 7 7 7 8 7 7 7 7: 7 194:208 224 144 240 176 240 224 208 240 224: 212 195: 0 0 0 0 0 0 0 0 0 0: 0 196:243 184 233 200 225 192 189 242 188 203: 209 197:255 0 0 0 255 0 255 0 0 255: 102 198:223 39 247 43 245 22 255 221 0 6: 130 199: 0 255 255 255 0 255 255 255 255 0: 178 200:231 225 251 1 252 20 211 216 218 16: 164 201: 0 0 0 0 0 0 0 0 0 0: 0 239: 21 138 196 87 26 89 16 245 187 144: 114 240: 0 0 0 0 0 0 0 0 0 0: 0
คอลัมน์แรกซ้ายสุดคือหมายเลขทะเบียน จากนั้นมาอ่าน 10 ครั้งสุดท้ายสำหรับการลงทะเบียนนั้น สุดท้าย คอลัมน์สุดท้ายคือค่าเฉลี่ยสำหรับแต่ละแถว
ดูเหมือนว่ารีจิสเตอร์ 61, 69, 71, 189, 197 และ 199 จะเป็นไบนารี่เท่านั้น หรือพร้อม/ไม่พร้อม หรือเป็นไบต์สูงของค่า 16 บิต (เชิงลบ?)
ข้อสังเกตอื่นๆ ที่น่าสนใจ:
- ทะเบียน 65, 193 - ค่าคงที่มากและเท่ากัน
- ทะเบียน 63, 191 - ค่าคงที่มากและเท่ากัน
- ทะเบียน 73, 112, 195, 201, 240 - ทั้งหมดเป็นศูนย์
มาเชื่อมโยงข้อสังเกตเหล่านี้กลับไปที่ภาพตารางที่เน้นสีหลายสีจากก่อนหน้านี้
ทะเบียน 65 - อุณหภูมิ
ทะเบียน 193 - ????????
ทะเบียน 63 - มาตรความเร่ง
ทะเบียน 191 - ????????
ทะเบียน 73 - ภายนอก
ลงทะเบียน 112 ขึ้นไป - ????????
เรายังคงมีสิ่งที่ไม่รู้จัก แต่เราได้เรียนรู้บางสิ่งที่เป็นประโยชน์
รีจิสเตอร์ 65 (อุณหภูมิ) และรีจิสเตอร์ 63 (มาตรความเร่ง) ทั้งคู่คงที่มาก นี่คือสิ่งที่เราคาดหวัง ฉันไม่ได้สัมผัสเซ็นเซอร์ มันไม่เคลื่อนไหว นอกจากการสั่นสะเทือนโดยไม่ได้ตั้งใจ เนื่องจากหุ่นยนต์วางอยู่บนโต๊ะเดียวกันกับคอมพิวเตอร์ของฉัน
มีการทดสอบที่น่าสนใจอย่างหนึ่งที่เราสามารถทำได้สำหรับการลงทะเบียนอุณหภูมิ/ตัวตรวจวัดความเร่งแต่ละตัว สำหรับการทดสอบนั้น เราต้องการโปรแกรมเวอร์ชันอื่น
ขั้นตอนที่ 7: เราสามารถส่งผลต่ออุณหภูมิและความเร่งได้
ในขั้นตอนก่อนหน้านี้ เราได้จำกัดการลงทะเบียนอุณหภูมิอย่างน้อยหนึ่งรายการ และอีกรายการสำหรับการเร่งความเร็ว
ด้วยเวอร์ชันถัดไปของโปรแกรม ("fifth.test.mpu9265.c") เราจะเห็นการเปลี่ยนแปลงที่เกิดขึ้นสำหรับการลงทะเบียนทั้งสอง โปรดดูวิดีโอ
ขุดเพิ่มเติม
หากเราย้อนกลับไปดูข้อมูลการลงทะเบียน เราจะพบว่ามี:
- เอาต์พุต 16 บิตสามช่องสำหรับไจโรสโคป
- เอาต์พุต 16 บิตสามตัวสำหรับมาตรความเร่ง
- เอาต์พุต 16 บิตสามช่องสำหรับเครื่องวัดสนามแม่เหล็ก
- เอาต์พุต 16 บิตหนึ่งตัวสำหรับอุณหภูมิ
อย่างไรก็ตาม ผลลัพธ์ที่ได้จากโปรแกรมทดสอบอย่างง่ายของเราคือเอาต์พุต 8 บิตเดียวทั้งหมด (ทะเบียนเดี่ยว).
มาลองใช้วิธีการเดียวกันนี้กันดีกว่า แต่คราวนี้อ่าน 16 บิตแทนที่จะเป็น 8
เราอาจจะต้องทำบางอย่างเช่นด้านล่าง ลองใช้อุณหภูมิเป็นตัวอย่าง เพราะมันเป็นเพียงเอาต์พุต 16 บิตเท่านั้น
//รับ file descriptor fd…
int tempRegHi = 65; int tempRegLo = 66; int hiByte = การเดินสายไฟPiI2CReadReg8 (fd, tempRegHi); int loByte = การเดินสายไฟPiI2CReadReg8(fd, tempRegLo); ผลลัพธ์ int = hiByte << 8; // ใส่คำสั่ง hi 8 บิตลงในส่วนบนของผลลัพธ์ค่า 16 บิต |= loByte; // ตอนนี้เพิ่มในลำดับ lo 8 บิต ให้ผลเป็นตัวเลข 16 บิตที่สมบูรณ์ // พิมพ์ตัวเลขนั้นหรือใช้ฟังก์ชันแสดงกราฟแนวนอนก่อนหน้านี้
จากขั้นตอนก่อนหน้านี้ เราเห็นว่ารีจิสเตอร์ 65 ค่อนข้างนิ่ง ในขณะที่รีจิสเตอร์ 66 นั้นดังมาก เนื่องจาก 65 เป็นไบต์ลำดับสูง และ 66 เป็นไบต์ลำดับต่ำ จึงสมเหตุสมผล
สำหรับการอ่าน เราสามารถเอาข้อมูลของ register 65 มาตามที่เป็นอยู่ แต่เราสามารถหาค่าเฉลี่ยของค่า register 66 ได้
หรือเราสามารถหาค่าเฉลี่ยของผลลัพธ์ทั้งหมดได้
ดูวิดีโอสุดท้ายสำหรับส่วนนี้ มันแสดงให้เห็นการอ่านค่าอุณหภูมิ 16 บิตทั้งหมด รหัสคือ "sixth.test.mpu9265.c"
ขั้นตอนที่ 8: มาตรความเร่งและไจโรสโคป
วิดีโอสำหรับส่วนนี้แสดงเอาต์พุตจากมาตรความเร่งและไจโรสโคป โดยใช้โปรแกรมทดสอบ "seventh.test.mpu9265.c" รหัสนั้นสามารถอ่าน 1, 2 หรือ 3 คู่ไบต์ติดต่อกัน (ไบต์สูงและต่ำ) และแปลงค่าเป็นค่า 16 บิตเดียว ดังนั้น เราสามารถอ่านแกนเดี่ยวใดๆ หรือเราสามารถอ่านสองแกนพร้อมกัน (และรวมการเปลี่ยนแปลง) หรือเราสามารถอ่านทั้งสามแกน (และรวมการเปลี่ยนแปลง)
เพื่อย้ำอีกครั้ง สำหรับขั้นตอนนี้ สำหรับคำแนะนำนี้ ฉันแค่ต้องการตอบคำถามง่ายๆ: "หุ่นยนต์หมุน/หมุนหรือไม่" ฉันไม่ได้มองหาค่าที่แม่นยำ เช่น มันหมุนได้ 90 องศาหรือเปล่า สิ่งนี้จะเกิดขึ้นในภายหลังเมื่อเราทำ SLAM แต่ไม่จำเป็นสำหรับการหลีกเลี่ยงสิ่งกีดขวางและการเคลื่อนไหวแบบสุ่ม
ขั้นตอนที่ 9: (กำลังดำเนินการ) Magnetometer
เมื่อใช้เครื่องมือ i2cdetect MPU9265 จะแสดงเป็น 0x68 ในตาราง:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
มีขั้นตอนเพิ่มเติมที่ต้องอ่านจากส่วนสนามแม่เหล็กของ IMU
จากเอกสาร PDF ของการลงทะเบียน Invesense:
ลงทะเบียน 37 ถึง 39 – I2C SLAVE 0 การควบคุม
- ลงทะเบียน 37 - I2C_SLV0_ADDR
- ลงทะเบียน 38 - I2C_SLV0_REG
- ลงทะเบียน 39 - I2C_SLV0_CTRL
แนะนำ:
Wallace the Animatronic Alien Creature: 9 ขั้นตอน (พร้อมรูปภาพ)
Wallace the Animatronic Alien Creature: ยินดีต้อนรับ! วันนี้ผมจะมานำเสนอวิธีการสร้าง Wallace สิ่งมีชีวิตเอเลี่ยนแอนิมาโทรนิกส์ ในการเริ่มต้น คุณจะต้องมี:x 1 สุนัข Fur Real Friends (เช่นนี้: https://www.ebay.com/p/1903566719)x 5 MG996R เซอร์โว x 1 Pololu Maestro 6-Channel Servo Contro
Bolt - DIY Wireless Charging Night Clock (6 ขั้นตอน): 6 ขั้นตอน (พร้อมรูปภาพ)
Bolt - DIY Wireless Charging Night Clock (6 ขั้นตอน): การชาร์จแบบเหนี่ยวนำ (เรียกอีกอย่างว่าการชาร์จแบบไร้สายหรือการชาร์จแบบไร้สาย) เป็นการถ่ายโอนพลังงานแบบไร้สาย ใช้การเหนี่ยวนำแม่เหล็กไฟฟ้าเพื่อจ่ายกระแสไฟฟ้าให้กับอุปกรณ์พกพา แอปพลิเคชั่นที่พบบ่อยที่สุดคือ Qi Wireless Charging st
ง่าย MPU6050 IMU + Arduino GYRO Bot: 4 ขั้นตอน
MPU6050 IMU + Arduino GYRO Bot อย่างง่าย: การใช้ Gyro เพื่อควบคุมโปรเจ็กต์ของฉันเป็นเรื่องใหญ่ในรายการฝากข้อมูลของฉัน แต่นอกเหนือจากการได้มาซึ่ง IMU แล้ว ส่วนที่เหลือยังยากเหมือนตะปู การขาดเนื้อหาที่มีประสิทธิภาพในการแยกค่าพิทช์หันเหและค่าการม้วนตัวทำให้ฉันสับสนนานกว่าหนึ่งเดือน หลังจากที่หลายเว็บไ
Bluetooth และ IMU พร้อม Tactigon Board - กำลังประมวลผล: 7 ขั้นตอน
Bluetooth และ IMU พร้อม Tactigon Board - กำลังประมวลผล: บทความชุดนี้จะอธิบายวิธีใช้เซ็นเซอร์และอินเทอร์เฟซการสื่อสารแบบบูรณาการของ Tactigon เพื่อสร้างตัวควบคุมท่าทางสัมผัสอย่างง่าย ซอร์สโค้ดมีให้ที่นี่บน GitHubในบทความนี้ เราจะมาเรียนรู้วิธี ใช้ซิม
SmartPhone Game Simulator- เล่นเกม Windows โดยใช้ Gesture Control IMU, Accelerometer, Gyroscope, Magnetometer: 5 ขั้นตอน
SmartPhone Game Simulator- เล่นเกม Windows โดยใช้ Gesture Control IMU, Accelerometer, Gyroscope, Magnetometer: สนับสนุนโครงการนี้: https://www.paypal.me/vslcreations โดยบริจาคให้กับโอเพ่นซอร์สโค้ด & สนับสนุนการพัฒนาต่อไป