Índice:
2025 Autor: John Day | [email protected]. Última modificação: 2025-01-13 06:58
Neste tutorial usaremos o giroscópio MPU6050, um anel de neopixel e um arduino para construir um dispositivo que acende os led's correspondentes ao ângulo de inclinação.
Este é um projeto simples e divertido e será montado em uma placa de ensaio. Se você seguir os passos, construirá o que viu no vídeo. É um bom tutorial para aprender sobre giroscópio e anel de neopixel.
Estou construindo este tutorial por causa do interesse que vi no meu primeiro instructable aqui (Gyroscope Led Control With Arduino). Neste instrutível, substituí o led simples por um anel de neopixel. O anel é mais simples de usar através de uma biblioteca Adafruit e é definitivamente mais espetacular.
Então, se você tem esses componentes espalhados, esta é uma ótima maneira de usá-los. Vou tentar guiá-lo passo a passo pela construção do dispositivo e também explicar como ele funciona na última etapa.
Etapa 1: Coisas necessárias
Peças
1. Arduino pro mini 328p (eBay) 2 $
2. Placa de ensaio
3. Giroscópio MPU6050 (eBay) 1,2 $
4. 24 anel led de neopixel (Adafruit) 17 $
5. 4 baterias AA com 4 baterias
6. Cabos de ligação em U (opcional). Usei esses cabos jumper porque eles ficam melhores na placa de ensaio e os leds são mais visíveis dessa forma. Você pode encontrar uma caixa de 140 no ebay por cerca de 4 $. Se você não tiver esses cabos, pode substituí-los por fios duplos.
Ferramentas:
1. USB para adaptador FTDI serial FT232RL para programar o arduino pro mini
2. Arduino IDE
Habilidades: 1. Soldando, verifique este tutorial
3. Programação básica do Arduino, este tutorial pode ser útil
Etapa 2: Montagem
Anexei o esquema fritzing no formato fzz e uma imagem dele para facilitar a visualização das conexões
1. Você precisa soldar 3 pinos machos na parte de trás do anel de neopixel como mostrado na imagem
- solde o pino positivo
- soldar o solo
- soldar o pino de entrada de dados
2. Em seguida, o suporte da bateria 4x deve ter uma maneira de se conectar à placa de ensaio, uma solução fácil é soldar dois fios duplos machos em seus terminais.
3. Prepare a placa de ensaio.
- coloque o anel de neopixel, microcontrolador e giroscópio na placa de ensaio como na imagem
- coloque todos os fios negativos: para o microcontrolador, anel de neopixel, giroscópio
- coloque todos os fios positivos: para o microcontrolador, anel de neopixel, giroscópio
- coloque todos os fios de dados:
* SDA e SCL do para o microcontrolador para o giroscópio
* pino D6 do microcontrolador para o anel de neopixel
- verifique todas as conexões antes de ligar
- opcionalmente, usando fita adesiva, prenda a bateria na parte de trás do bradboard para prendê-la no lugar e torná-la mais portátil
Etapa 3: O Código e Calibração
Primeiro você precisa baixar e instalar duas bibliotecas:
1. Biblioteca de neopixel Adafruit para controlar o neopixel
2. Biblioteca MPU6050 para o giroscópio
3. Fonte da biblioteca I2CDev
São duas grandes bibliotecas que farão o trabalho pesado!
Mais detalhes sobre os neopixels aqui
Em seguida, baixe e instale minha biblioteca aqui ou copie abaixo:
#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; Tira Adafruit_NeoPixel = Adafruit_NeoPixel (NUM_LEDS, NEOPIXED_CONTROL_PIN, NEO_RBG + NEO_KHZ800); não assinado long lastPrintTime = 0; inicialização bool = falso; // define verdadeiro se a inicialização DMP foi bem-sucedida uint8_t mpuIntStatus; // mantém o byte de status de interrupção real do MPU uint8_t devStatus; // retorna o status após cada operação do dispositivo (0 = sucesso,! 0 = erro) uint16_t packetSize; // tamanho do pacote DMP esperado (o padrão é 42 bytes) uint16_t fifoCount; // contagem de todos os bytes atualmente em FIFO uint8_t fifoBuffer [64]; // buffer de armazenamento FIFO Quaternion q; // [w, x, y, z] contêiner de quatérnio VectorFloat gravity; // [x, y, z] vetor de gravidade float ypr [3]; // [yaw, pitch, roll] yaw / pitch / roll container e vetor de gravidade volátil bool mpuInterrupt = false; // indica se o pino de interrupção MPU foi alto
void setup ()
{Serial.begin (9600); Serial.println ("Programa iniciado"); inicialização = inicializarGiroscópio (); strip.begin (); } void loop () {if (! inicialização) {return; } mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus (); fifoCount = mpu.getFIFOCount (); if (hasFifoOverflown (mpuIntStatus, fifoCount)) {mpu.resetFIFO (); Retorna; } if (mpuIntStatus & 0x02) {while (fifoCount <packetSize) {fifoCount = mpu.getFIFOCount (); } mpu.getFIFOBytes (fifoBuffer, packetSize); fifoCount - = tamanho do pacote; 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); }} boolean 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 = restrição (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) {ângulo duplo = (atan ((duplo) abs (x) / (duplo) abs (y)) * 4068) / 71; int ledNr = mapa (ângulo, deAngle, toAngle, fromLedPosition, toLedPosition); printDebug (x, y, ledNr, ângulo); uint32_t color; para (int i = 0; posição i + LED_OFFSET) {posição de retorno + LED_OFFSET; } posição de retorno + LED_OFFSET - NUM_LEDS; } void printDebug (int y, int z, int lightLed, int ângulo) {if (millis () - lastPrintTime <500) {return; } Serial.print ("a ="); Serial.print (ângulo); 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 ("MPU6050 conexão bem-sucedida"): F ("MPU6050 conexão falhou")); Serial.println (F ("Inicializando DMP…")); devStatus = mpu.dmpInitialize (); mpu.setXGyroOffset (220); mpu.setYGyroOffset (76); mpu.setZGyroOffset (-85); mpu.setZAccelOffset (1788); if (devStatus! = 0) {Serial.print (F ("Falha na inicialização do DMP (código")); Serial.println (devStatus); retornar falso;} mpu.setDMPEnabled (true); Serial.println (F ("Ativando detecção de interrupção (interrupção externa do Arduino 0)… ")); attachInterrupt (0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus (); Serial.println (F (" DMP pronto! Aguardando a primeira interrupção… ")); Tamanho do pacote = mpu.dmpGetFIFOPacketSize (); retornar verdadeiro;} void dmpDataReady () {mpuInterrupt = true;}
Faça upload do código:
Usando o adaptador FTDI, faça upload do código para o arduino.
Conecte a fonte de alimentação (baterias)
Calibração:
A coisa mais importante a calibrar aqui é a constante "LED_OFFSET". No meu exemplo é 12. Você precisa ajustar isso de 0 a 23 para que, após ligar a placa, o led acenda na direção em que você inclinar a placa.
Se você quiser saber mais detalhes sobre como funciona, dê uma olhada na última etapa
Etapa 4: como funciona (opcional)
Primeiro algumas informações sobre o giroscópio MPU6050. Este é um giroscópio MEMS (MEMS significa sistemas microeletromecânicos).
Cada tipo de giroscópio MEMs tem alguma forma de componente oscilante de onde a accleração e, portanto, a mudança de direção podem ser detectadas. Isso ocorre porque, de acordo com a lei de conservação do movimento, um objeto vibrando gosta de continuar vibrando no mesmo plano, e qualquer desvio vibracional pode ser usado para derivar uma mudança de direção.
O giroscópio também contém um microcontrolador próprio para calcular o roll, pitch e yaw por meio de algumas matemáticas sofisticadas.
Mas os dados brutos do giroscópio sofrem de ruído e deriva, então usamos uma biblioteca externa para suavizar as coisas e nos fornecer dados utilizáveis limpos.
Os Neopixel são leds RGB endereçáveis individualmente e encadeados em faixas e anéis. Eles funcionam em 5V e contêm seus próprios circuitos, então você só precisa alimentar os neopixels e se comunicar com eles usando a linha de dados. A comunicação é feita com uma única linha de dados contendo relógio e dados (mais detalhes aqui). Adafruit fornece uma biblioteca limpa para interagir com os anéis de neopixel.
O código
Dentro da função l oop (), a biblioteca MPU6050_6Axis_MotionApps20 é chamada. Quando a biblioteca tem novos dados do giroscópio, ela chama redrawLeds (x, y, z) com 3 argumentos que representam yaw, pitch e roll
Inside redrawLeds ():
- estamos nos concentrando em dois eixos: y, z
- estamos restringindo ambos os eixos de -MAX_ANGLE a + MAX_ANGLE, definimos o ângulo máximo para 45 e é alterável
- estamos dividindo 360 graus em 4 quadrantes e chamamos as funções lightLeds () para cada um da seguinte maneira:
* y negativo, z positivo no primeiro quadrante controlará os leds de 0 a 5, o ângulo será de 0 a 89
* y negativo, o segundo quadrante z negativo controla os leds de 6 a 12, o ângulo será de 89 a 0
* … etc
- dentro da função lightLeds
* estou calculando um ângulo com base nos dois eixos usando arco tangente (verifique a imagem anexa)
* Estou calculando o que levou a mostrar usando a função de mapa do Arduino
* Estou redefinindo a faixa de led, exceto dois led's, o que corresponde à posição led que calculei antes e uma posição led antes (para mostrar um efeito de desvanecimento)
* Estou usando uma função chamada normalizeLedPosition () para levar em consideração a calibração do neopixel. A calibração é útil porque o anel de neopixel pode ser girado conforme desejado e deve estar alinhado com o giroscópio
* também estou imprimindo o eixo de reboque, o led tem luz e o ângulo
A matemática
Anexei uma imagem com o anel led e a função trigonométrica usada para determinar o ângulo.