สารบัญ:

Gyroscope สนุกไปกับ Neopixel Ring: 4 ขั้นตอน (พร้อมรูปภาพ)
Gyroscope สนุกไปกับ Neopixel Ring: 4 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: Gyroscope สนุกไปกับ Neopixel Ring: 4 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: Gyroscope สนุกไปกับ Neopixel Ring: 4 ขั้นตอน (พร้อมรูปภาพ)
วีดีโอ: วงจรนาฬิกาแบบวงกลมสร้างจาก NeoPixel - EP.52 2024, พฤศจิกายน
Anonim
Image
Image

ในบทช่วยสอนนี้ เราจะใช้ไจโรสโคป MPU6050, แหวนนีโอพิกเซลและอาร์ดิโนเพื่อสร้างอุปกรณ์ที่ไฟ LED ให้สอดคล้องกับมุมเอียง

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

ฉันกำลังสร้างบทช่วยสอนนี้เนื่องจากความสนใจที่ฉันเห็นในคำสั่งแรกของฉันที่นี่ (Gyroscope Led Control ด้วย Arduino) ในคำแนะนำนี้ฉันได้แทนที่ไฟ LED แบบธรรมดาด้วยวงแหวนนีโอพิกเซล แหวนนี้ใช้ง่ายกว่าในห้องสมุด Adafruit และงดงามยิ่งขึ้นอย่างแน่นอน

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

ขั้นตอนที่ 1: สิ่งที่จำเป็น

การประกอบ
การประกอบ

อะไหล่

1. Arduino pro mini 328p (eBay) 2 $

2. เขียงหั่นขนม

3. MPU6050 ไจโรสโคป (eBay) 1.2$

4. 24 neopixel led ring (อดาฟรุ๊ต) 17 $

5. ก้อนแบตเตอรี่ AA x 4 ก้อนพร้อมแบตเตอรี่ 4 ก้อน

6. สายจัมเปอร์รูปตัวยู (อุปกรณ์เสริม) ฉันเคยใช้สายจัมเปอร์เหล่านี้เพราะมันดูดีกว่าบนเขียงหั่นขนม และไฟ LED จะมองเห็นได้ชัดเจนขึ้นด้วยวิธีนี้ คุณสามารถหากล่อง 140 บนอีเบย์ได้ที่ประมาณ 4$ หากคุณไม่มีสายเคเบิลเหล่านี้ คุณสามารถแทนที่ด้วยสายดูปองท์

เครื่องมือ:

1. USB เข้ากับอะแดปเตอร์ FTDI อนุกรม FT232RL เพื่อตั้งโปรแกรม Arduino pro mini

2. Arduino IDE

ทักษะ:1. การบัดกรี ตรวจสอบบทช่วยสอนนี้

3. การเขียนโปรแกรม Arduino ขั้นพื้นฐาน บทช่วยสอนนี้อาจเป็นประโยชน์

ขั้นตอนที่ 2: การประกอบ

การประกอบ
การประกอบ

ฉันได้แนบแผนผัง fritzing ในรูปแบบ fzz และรูปภาพเพื่อให้มองเห็นการเชื่อมต่อได้ง่าย

1. คุณต้องบัดกรีหมุดตัวผู้ 3 ตัวที่ด้านหลังของวงแหวนนีโอพิกเซลตามที่แสดงในภาพ

- ประสานพินบวก

- ประสานพื้น

- ประสานพินอินพุตข้อมูล

2. จากนั้นที่ใส่แบตเตอรี่ 4x ควรมีวิธีการเชื่อมต่อกับเขียงหั่นขนม วิธีแก้ไขที่ง่ายคือการบัดกรีสายดูปองท์ตัวผู้สองตัวเข้ากับขั้วของมัน

3. เตรียมเขียงหั่นขนม

- วางวงแหวนนีโอพิกเซล ไมโครคอนโทรลเลอร์ และไจโรสโคปบนเขียงหั่นขนมเหมือนในภาพ

- วางสายลบทั้งหมด: ไปที่ไมโครคอนโทรลเลอร์, วงแหวนนีโอพิกเซล, ไจโร

- วางสายบวกทั้งหมด: ไปที่ไมโครคอนโทรลเลอร์, วงแหวนนีโอพิกเซล, ไจโร

- วางสายข้อมูลทั้งหมด:

* SDA และ SCL จากไมโครคอนโทรลเลอร์ไปยังไจโร

* ปักหมุด D6 จากไมโครคอนโทรลเลอร์ไปที่วงแหวนนีโอพิกเซล

- ตรวจสอบการเชื่อมต่อทั้งหมดอีกครั้งก่อนเปิดเครื่อง

- เลือกใช้เทปพันสายไฟ ติดเทปก้อนแบตเตอรี่ที่ด้านหลังของ bradboard เพื่อยึดเข้าที่และทำให้พกพาสะดวกยิ่งขึ้น

ขั้นตอนที่ 3: รหัสและการสอบเทียบ

ก่อนอื่นคุณต้องดาวน์โหลดและติดตั้งสองไลบรารี:

1. Adafruit neopixel library fir ควบคุม neopixel

2. ห้องสมุด MPU6050 สำหรับไจโรสโคป

3. แหล่งที่มาของไลบรารี I2CDev

พวกเขาเป็นห้องสมุดที่ยอดเยี่ยมสองแห่งที่จะทำงานหนัก!

รายละเอียดเพิ่มเติมเกี่ยวกับนีโอพิกเซลที่นี่

จากนั้นดาวน์โหลดและติดตั้งห้องสมุดของฉันจากที่นี่หรือคัดลอกจากด้านล่าง:

#รวม "I2Cdev.h"

#include #include "MPU6050_6Axis_MotionApps20.h" #include "Wire.h" #define NEOPIXED_CONTROL_PIN 6 #define NUM_LEDS 24 const int MAX_ANGLE = 45; const int LED_OFFSET = 12; MPU6050 เอ็มพียู; แถบ Adafruit_NeoPixel = Adafruit_NeoPixel (NUM_LEDS, NEOPIXED_CONTROL_PIN, NEO_RBG + NEO_KHZ800); LastPrintTime แบบยาวที่ไม่ได้ลงชื่อ = 0; การเริ่มต้นบูล = เท็จ; // ตั้งค่าจริงหาก DMP init สำเร็จ uint8_t mpuIntStatus; // เก็บไบต์สถานะขัดจังหวะจริงจาก MPU uint8_t devStatus; // ส่งคืนสถานะหลังจากการทำงานของอุปกรณ์แต่ละเครื่อง (0 = สำเร็จ, !0 = ข้อผิดพลาด) uint16_t packetSize; // ขนาดแพ็กเก็ต DMP ที่คาดไว้ (ค่าเริ่มต้นคือ 42 ไบต์) uint16_t fifoCount; // นับไบต์ทั้งหมดที่อยู่ใน FIFO uint8_t fifoBuffer[64]; // บัฟเฟอร์การจัดเก็บ FIFO Quaternion q; // [w, x, y, z] คอนเทนเนอร์ควอเทอร์เนียน VectorFloat แรงโน้มถ่วง; // [x, y, z] เวกเตอร์แรงโน้มถ่วง float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container และเวกเตอร์แรงโน้มถ่วง bool mpuInterrupt = false; // ระบุว่าพินขัดจังหวะ MPU สูงหรือไม่

การตั้งค่าเป็นโมฆะ ()

{ Serial.begin(9600); Serial.println("เริ่มโปรแกรม"); การเริ่มต้น = initializeGyroscope(); แถบ.begin(); } void loop() { if (!initialization) { return; } mpuInterrupt = เท็จ; mpuIntStatus = mpu.getIntStatus (); fifoCount = mpu.getFIFOCount(); ถ้า (hasFifoOverflown (mpuIntStatus, fifoCount)) { mpu.resetFIFO (); กลับ; } if (mpuIntStatus & 0x02) { ในขณะที่ (fifoCount < packetSize) { fifoCount = mpu.getFIFOCount (); } mpu.getFIFOBytes (fifoBuffer, packetSize); fifoCount -= ขนาดแพ็คเก็ต; mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&แรงโน้มถ่วง &q); mpu.dmpGetYawPitchRoll(ypr, &q, &แรงโน้มถ่วง); redrawLeds(ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI); } } บูลีน hasFifoOverflown (int mpuIntStatus, int fifoCount) { ส่งคืน mpuIntStatus & 0x10 || fifoCount == 1024; } เป็นโมฆะ redrawLeds (int x, int y, int z) { x = ข้อ จำกัด (x, -1 * MAX_ANGLE, MAX_ANGLE); y = ข้อจำกัด (y, -1 * MAX_ANGLE, MAX_ANGLE); ถ้า (y 0) { lightLeds (y, z, 0, 5, 0, 89); } อื่น ๆ ถ้า (y < 0 และ z 0 และ z 0 และ z > 0) { lightLeds (y, z, 20, 24, 89, 0); } } โมฆะ lightLeds (int x, int y, int fromLedPosition, int toLedPosition, int fromAngle, int toAngle) { double angle = (atan((double) abs(x) / (double) abs (y)) * 4068) / 71; int ledNr = แผนที่ (มุม, จากมุม, ถึงมุม, จากLedPosition, toLedPosition); printDebug(x, y, ledNr, มุม); uint32_t สี; สำหรับ (int i=0; ตำแหน่ง i + LED_OFFSET) { ตำแหน่งกลับ + LED_OFFSET; } ตำแหน่งกลับ + LED_OFFSET - NUM_LEDS; } โมฆะ printDebug (int y, int z, int lightLed, int angle) { if (millis() - lastPrintTime < 500) { return; } Serial.print("a=");Serial.print(มุม);Serial.print("; "); Serial.print("ll=");Serial.print(lightLed);Serial.print("; "); Serial.print("ll=");อนุกรม.print(lightLed);Serial.print("; "); Serial.print("y=");Serial.print(y);Serial.print("; "); อนุกรม.print("y=");Serial.print(y);Serial.print("; "); Serial.print("z=");Serial.print(z);Serial.println("; "); Serial.print("z=");อนุกรม.print(z);Serial.println("; "); lastPrintTime = มิลลิวินาที (); } bool initializeGyroscope() { Wire.begin(); TWBR = 24; mpu.initialize(); Serial.println(mpu.testConnection() ? F("การเชื่อมต่อ MPU6050 สำเร็จ"): F("การเชื่อมต่อ MPU6050 ล้มเหลว")); Serial.println(F("กำลังเริ่มต้น DMP…")); devStatus = mpu.dmp เริ่มต้น (); mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1788); ถ้า (devStatus != 0) { Serial.print (F ("DMP Initialization ล้มเหลว (รหัส ")); Serial.println (devStatus); return false; } mpu.setDMPEnabled (จริง); Serial.println (F ("เปิดใช้งาน การตรวจจับการขัดจังหวะ (Arduino อินเตอร์รัปต์ภายนอก 0)…")); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); Serial.println(F("DMP ready! Waiting for first interrupt…")); packetSize = mpu.dmpGetFIFOPacketSize (); คืนค่าจริง; } เป็นโมฆะ dmpDataReady () { mpuInterrupt = จริง; }

อัปโหลดรหัส:

การใช้อะแดปเตอร์ FTDI อัปโหลดรหัสไปยัง Arduino

เชื่อมต่อแหล่งจ่ายไฟ (แบตเตอรี่)

การสอบเทียบ:

สิ่งสำคัญที่สุดในการปรับเทียบที่นี่คือค่าคงที่ "LED_OFFSET" ในตัวอย่างของฉันคือ 12 คุณต้องปรับค่านี้จาก 0 ถึง 23 เพื่อที่ว่าหลังจากเปิดเครื่องแล้ว ไฟ LED จะสว่างไปในทิศทางที่คุณเอียงกระดาน

หากคุณต้องการทราบรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงาน โปรดอ่านขั้นตอนสุดท้าย

ขั้นตอนที่ 4: มันทำงานอย่างไร (ไม่บังคับ)

มันทำงานอย่างไร (ไม่บังคับ)
มันทำงานอย่างไร (ไม่บังคับ)

ก่อนอื่น ข้อมูลเล็กน้อยเกี่ยวกับไจโรสโคป MPU6050 นี่คือไจโรสโคป MEMS (MEMS ย่อมาจากระบบไมโครไฟฟ้า)

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

ไจโรยังมีไมโครคอนโทรลเลอร์ของตัวเองเพื่อคำนวณการหมุน ขว้าง และหันเหผ่านคณิตศาสตร์แฟนซี

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

Neopixel เป็นไฟ LED RGB ที่สามารถระบุตำแหน่งได้และถูกล่ามโซ่เป็นแถบและวงแหวน พวกมันทำงานบนไฟ 5V และมีวงจรของตัวเอง คุณเพียงแค่จ่ายไฟให้กับนีโอพิกเซลและสื่อสารกับพวกมันโดยใช้สายข้อมูล การสื่อสารเสร็จสิ้นด้วยสายข้อมูลเดียวที่มีนาฬิกาและข้อมูล (รายละเอียดเพิ่มเติมที่นี่) Adafruit มีห้องสมุดที่สะอาดสำหรับการโต้ตอบกับวงแหวนนีโอพิกเซล

รหัส

ภายในฟังก์ชัน l oop() จะมีการเรียกไลบรารี MPU6050_6Axis_MotionApps20 เมื่อไลบรารีมีข้อมูลใหม่จาก gyroscpe จะเรียก redrawLeds(x, y, z) โดยมี 3 อาร์กิวเมนต์แทน yaw, pitch และ roll

ภายใน redrawLeds ():

- เรากำลังโฟกัสสองแกน: y, z

- เรากำลังจำกัดทั้งสองแกนจาก -MAX_ANGLE ถึง +MAX_ANGLE เรากำหนดมุมสูงสุดเป็น 45 และสามารถเปลี่ยนแปลงได้

- เรากำลังแบ่ง 360 องศาออกเป็น 4 ส่วนและเรียกฟังก์ชัน lightLeds() สำหรับแต่ละส่วนดังนี้:

* y ลบ, z จตุภาคแรกที่เป็นบวกจะควบคุม LED จาก 0 ถึง 5, มุมจะอยู่ระหว่าง 0 ถึง 89

* y ลบ, z ตัวควบคุมในจตุภาคที่สองที่เป็นลบนำจาก 6 ถึง 12, มุมจะอยู่ระหว่าง 89 ถึง 0

* …ฯลฯ

- ภายในฟังก์ชั่น lightLeds

* ฉันกำลังคำนวณมุมจากสองแกนโดยใช้อาร์กแทนเจนต์ (ตรวจสอบภาพที่แนบมา)

* ฉันกำลังคำนวณสิ่งที่นำไปสู่การแสดงโดยใช้ฟังก์ชันแผนที่ Arduino

* ฉันกำลังรีเซ็ตแถบไฟ LED ทั้งหมดยกเว้น LED สองดวง โดยอันที่ตรงกับตำแหน่ง LED ที่ฉันคำนวณไว้ก่อนหน้านี้และตำแหน่ง LED ก่อนหน้านี้ (เพื่อแสดงเอฟเฟกต์จาง)

* ฉันใช้ฟังก์ชันที่เรียกว่า normalizeLedPosition() เพื่อพิจารณาการปรับเทียบนีโอพิกเซล การปรับเทียบมีประโยชน์เพราะสามารถหมุนวงแหวนนีโอพิกเซลได้ตามต้องการ และควรจัดวางให้ชิดกับไจโรสโคป

* ฉันกำลังพิมพ์แกนลากด้วยสิ่งที่นำมีแสงและมุม

คณิตศาสตร์

ฉันได้แนบรูปภาพที่มีวงแหวน LED และฟังก์ชันตรีโกณมิติที่ใช้ในการกำหนดมุม

แนะนำ: