Sommario:

Divertimento con giroscopio con anello in neopixel: 4 passaggi (con immagini)
Divertimento con giroscopio con anello in neopixel: 4 passaggi (con immagini)

Video: Divertimento con giroscopio con anello in neopixel: 4 passaggi (con immagini)

Video: Divertimento con giroscopio con anello in neopixel: 4 passaggi (con immagini)
Video: GIOCOLERIA con ANELLI: trick e idee per iniziare || Geocolerie d'appartamento 2024, Dicembre
Anonim
Image
Image

In questo tutorial utilizzeremo il giroscopio MPU6050, un anello in neopixel e un arduino per costruire un dispositivo che accenda dei led corrispondenti all'angolo di inclinazione.

Questo è un progetto semplice e divertente e verrà assemblato su una breadboard. Se seguirai i passaggi, costruirai ciò che hai visto nel video. È un buon tutorial per conoscere il giroscopio e l'anello neopixel.

Sto costruendo questo tutorial a causa dell'interesse che ho visto sul mio primo istruibile qui (Gyroscope Led Control With Arduino). In questo tutorial ho sostituito semplici led con un anello neopixel. L'anello è più semplice da usare tramite una libreria Adafruit ed è decisamente più spettacolare.

Quindi, se hai questi componenti in giro, questo è un ottimo modo per usarli, cercherò di guidarti passo dopo passo attraverso la costruzione del dispositivo e spiegherò anche come funziona nell'ultimo passaggio.

Passaggio 1: cose necessarie

Assemblea
Assemblea

Parti

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

2. Tagliere

3. Giroscopio MPU6050 (eBay) 1.2$

4. Anello led da 24 neopixel (Adafruit) 17 $

5. 4 batterie AA con 4 batterie

6. Cavi jumper a forma di U (opzionali). Ho usato questi cavi jumper perché hanno un aspetto migliore sulla breadboard e i led sono più visibili in questo modo. Puoi trovare una scatola da 140 su ebay a circa 4$. Se non hai questi cavi puoi sostituirli con cavi Dupont.

Utensili:

1. Adattatore FTDI da USB a seriale FT232RL per programmare arduino pro mini

2. Arduino IDE

Abilità:1. Saldatura, controlla questo tutorial

3. Programmazione Arduino di base, questo tutorial potrebbe essere utile

Passaggio 2: assemblaggio

Assemblea
Assemblea

Ho allegato il fritzing schematico in formato fzz e una sua foto per una facile visualizzazione delle connessioni

1. È necessario saldare 3 pin maschio sul retro dell'anello neopixel come mostrato nell'immagine

- saldare il pin positivo

- saldare il terreno

- saldare il pin di input dei dati

2. Quindi il supporto della batteria 4x dovrebbe avere un modo per collegarsi alla breadboard, una soluzione semplice è saldare due cavi dupont maschi ai suoi terminali.

3. Preparare la breadboard.

- posiziona l'anello neopixel, il microcontrollore e il giroscopio sulla breadboard come nell'immagine

- posizionare tutti i fili negativi: al microcontrollore, anello neopixel, giroscopio

- posizionare tutti i fili positivi: al microcontrollore, anello neopixel, giroscopio

- posizionare tutti i cavi dati:

* SDA e SCL dal al microcontrollore al giroscopio

* pin D6 dal microcontrollore all'anello neopixel

- ricontrollare tutte le connessioni prima di alimentare

- facoltativamente utilizzando del nastro adesivo, fissare il pacco batteria sul retro del bradboard per tenerlo in posizione e renderlo più portatile

Passaggio 3: il codice e la calibrazione

Per prima cosa devi scaricare e installare due librerie:

1. Libreria Adafruit neopixel per il controllo del neopixel

2. Libreria MPU6050 per il giroscopio

3. Sorgente della libreria I2CDev

Sono due grandi librerie che faranno il lavoro pesante!

Maggiori dettagli sui neopixel qui

Quindi scarica e installa la mia libreria da qui o copiala da sotto:

#include "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 MPU; Striscia Adafruit_NeoPixel = Adafruit_NeoPixel(NUM_LEDS, NEOPIXED_CONTROL_PIN, NEO_RBG + NEO_KHZ800); unsigned long lastPrintTime = 0; inizializzazione bool = false; // imposta true se DMP init ha avuto successo uint8_t mpuIntStatus; // mantiene il byte di stato dell'interrupt effettivo dalla MPU uint8_t devStatus; // restituisce lo stato dopo ogni operazione del dispositivo (0 = successo, !0 = errore) uint16_t packetSize; // dimensione prevista del pacchetto DMP (il valore predefinito è 42 byte) uint16_t fifoCount; // conteggio di tutti i byte attualmente in FIFO uint8_t fifoBuffer[64]; // Buffer di memorizzazione FIFO Quaternion q; // [w, x, y, z] contenitore di quaternioni VectorFloat gravità; // [x, y, z] vettore gravità float ypr[3]; // [imbardata, beccheggio, rollio] contenitore imbardata/beccheggio/rollio e vettore di gravità volatile bool mpuInterrupt = false; // indica se il pin di interruzione MPU è andato alto

configurazione nulla()

{ Serial.begin(9600); Serial.println("Programma avviato"); inizializzazione = initializeGyroscope(); strip.begin(); } void loop() { if (! inizializzazione) { return; } mpuInterrupt = falso; mpuIntStatus = mpu.getIntStatus(); fifoCount = mpu.getFIFOCount(); if (hasFifoOverflown(mpuIntStatus, fifoCount)) { mpu.resetFIFO(); Restituzione; } if (mpuIntStatus & 0x02) { while (fifoCount < packetSize) { fifoCount = mpu.getFIFOCount(); } mpu.getFIFOBytes(fifoBuffer, packetSize); fifoCount -= dimensione pacchetto; mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); redrawLeds(ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI); } } booleano hasFifoOverflown(int mpuIntStatus, int fifoCount) { return mpuIntStatus & 0x10 || fifoCount == 1024; } void redrawLeds(int x, int y, int z) { x = constrain(x, -1 * MAX_ANGLE, MAX_ANGLE); y = constrain(y, -1 * MAX_ANGLE, MAX_ANGLE); if (y 0) { lightLeds(y, z, 0, 5, 0, 89); } else if (y < 0 e z 0 e z 0 e z > 0) { lightLeds(y, z, 20, 24, 89, 0); } } void 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 = map(angle, fromAngle, toAngle, fromLedPosition, toLedPosition); printDebug(x, y, ledNr, angolo); uint32_t colore; for (int i=0; i posizione + LED_OFFSET) { ritorno posizione + LED_OFFSET; } posizione di ritorno + LED_OFFSET - NUM_LEDS; } void printDebug(int y, int z, int lightLed, int angle) { if (millis() - lastPrintTime < 500) { return; } Serial.print("a=");Serial.print(angolo);Serial.print("; "); Serial.print("ll=");Serial.print(lightLed);Serial.print("; "); Serial.print("y=");Serial.print(y);Serial.print("; "); Serial.print("z=");Serial.print(z);Serial.println("; "); lastPrintTime = millis(); } bool initializeGyroscope() { Wire.begin(); TWBR = 24; mpu.initialize(); Serial.println(mpu.testConnection() ? F("Connessione MPU6050 riuscita"): F("Connessione MPU6050 non riuscita")); Serial.println(F("Inizializzazione DMP…")); devStatus = mpu.dmpInitialize(); mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1788); if (devStatus != 0) { Serial.print(F("Inizializzazione DMP non riuscita (codice "));Serial.println(devStatus); return false; } mpu.setDMPEnabled(true); Serial.println(F("Abilitazione rilevamento degli interrupt (Arduino external interrupt 0)…")); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); Serial.println(F("DMP pronto! In attesa del primo interrupt…")); packetSize = mpu.dmpGetFIFOPacketSize(); return true; } void dmpDataReady() { mpuInterrupt = true; }

Carica il codice:

Usando l'adattatore FTDI carica il codice su arduino.

Collegare l'alimentazione (batterie)

Calibrazione:

La cosa più importante da calibrare qui è la costante "LED_OFFSET". Nel mio esempio è 12. Devi regolarlo da 0 a 23 in modo che dopo aver alimentato la scheda il led si illumini nella direzione in cui inclini la scheda.

Se vuoi scoprire maggiori dettagli su come funziona controlla l'ultimo passaggio

Passaggio 4: come funziona (opzionale)

Come funziona (opzionale)
Come funziona (opzionale)

Prima alcune informazioni sul giroscopio MPU6050. Questo è un giroscopio MEMS (MEMS sta per sistemi microelettromeccanici).

Ogni tipo di giroscopio MEM ha una qualche forma di componente oscillante da cui è possibile rilevare l'accelerazione, e quindi il cambio di direzione. Questo perché, secondo la legge di conservazione del moto, a un oggetto vibrante piace continuare a vibrare sullo stesso piano e qualsiasi deviazione vibrazionale può essere utilizzata per derivare un cambiamento di direzione.

Il giroscopio contiene anche un proprio microcontrollore per calcolare rollio, beccheggio e imbardata attraverso alcuni calcoli fantasiosi.

Ma i dati grezzi del giroscopio soffrono di rumore e deriva, quindi abbiamo utilizzato una libreria esterna per appianare le cose e fornirci dati utilizzabili puliti.

I Neopixel sono led RGB indirizzabili singolarmente e concatenati in fasce e anelli. Funzionano a 5V e contengono i propri circuiti quindi è sufficiente alimentare i neopixel e comunicare con loro utilizzando la linea dati. La comunicazione avviene con una singola linea dati contenente orologio e dati (maggiori dettagli qui). Adafruit fornisce una libreria pulita per interagire con gli anelli neopixel.

Il codice

All'interno della funzione l oop() viene chiamata la libreria MPU6050_6Axis_MotionApps20. Quando la libreria ha nuovi dati dal giroscopio chiama redrawLeds(x, y, z) con 3 argomenti che rappresentano imbardata, beccheggio e rollio

All'interno redrawLeds ():

- ci stiamo concentrando su due assi: y, z

- stiamo vincolando entrambi gli assi da -MAX_ANGLE a +MAX_ANGLE, abbiamo definito l'angolo massimo a 45 ed è modificabile

- stiamo suddividendo 360 gradi in 4 quadranti e chiamiamo le funzioni lightLeds() per ciascuno come segue:

* y negativo, z positivo il primo quadrante controllerà i led da 0 a 5, l'angolo sarà da 0 a 89

* y negativo, z negativo secondo quadrante controlla i led da 6 a 12, l'angolo sarà da 89 a 0

* …eccetera

- all'interno della funzione lightLeds

* sto calcolando un angolo in base ai due assi usando l'arcotangente (controlla l'immagine allegata)

* sto calcolando cosa ha portato a mostrare usando la funzione mappa di arduino

* sto ripristinando la striscia led tutti tranne due led, quello corrispondente alla posizione del led che ho calcolato prima e una posizione del led prima (per mostrare un effetto di dissolvenza)

* Sto usando una funzione chiamata normalizeLedPosition() per prendere in considerazione la calibrazione del neopixel. La calibrazione è utile perché l'anello neopixel può essere ruotato a piacimento e deve essere allineato con il giroscopio

* sto stampando anche l'asse di traino, quale led ha la luce e l'angolo

La matematica

Ho allegato una foto con l'anello led e la funzione trigonometrica utilizzata per determinare l'angolo.

Consigliato: