Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Display Interativo de Giroscópio com Anel NeoPixel e Arduino

Componentes e Materiais

ComponenteQuantidade
Arduino Pro Mini 328 - 5V/16MHz (SparkFun)1
Anel NeoPixel Adafruit: WS2812 5050 RGB LED (24 LEDs)1
Breakout IMU SparkFun - MPU-9250 (ou MPU6050)1
Protoboard (genérico)1
Jumpers Macho-Macho1
Jumpers Macho-Fêmea1
Suporte para 4 pilhas AA + pilhas1

Sobre o Projeto

Neste tutorial, utilizamos o giroscópio MPU6050, um Anel NeoPixel e um Arduino para construir um dispositivo que acende LEDs correspondentes ao ângulo de inclinação.

É um projeto simples e divertido, montado em protoboard. Ao seguir os passos, você construirá o que viu no vídeo. É um excelente tutorial para aprender sobre giroscópio e anel NeoPixel.

Substituí LEDs simples por um Anel NeoPixel, que é mais simples de usar através da biblioteca Adafruit e visualmente mais espetacular.

Se você tem esses componentes guardados, esta é uma ótima maneira de utilizá-los. Vou guiá-lo passo a passo na construção e explicar o funcionamento no final.

Passo 1: Materiais Necessários

Peças:

  1. Arduino Pro Mini 328P
  2. Protoboard
  3. Giroscópio MPU6050
  4. Anel NeoPixel de 24 LEDs
  5. Suporte 4x pilhas AA com pilhas
  6. Jumpers em U (opcional) - ficam melhor na protoboard e deixam LEDs mais visíveis. Caixa com 140 no eBay por ~$4. Se não tiver, use jumpers Dupont.

Ferramentas:

  1. Adaptador USB-serial FTDI FT232RL para programar o Arduino Pro Mini
  2. Arduino IDE

Habilidades: Soldagem e programação básica de Arduino.

Passo 2: Montagem

O esquemático Fritzing em formato .fzz e uma imagem estão anexos para fácil visualização das conexões.

  1. Soldar 3 pinos macho na parte traseira do anel NeoPixel:
    • Pino positivo (VCC)
    • Terra (GND)
    • Pino de entrada de dados (DIN)
  2. O suporte de 4 pilhas precisa de conexão para a protoboard: solde dois jumpers macho Dupont nos terminais.
  3. Prepare a protoboard:
    • Posicione o anel NeoPixel, microcontrolador e giroscópio como na imagem
    • Conecte todos os fios negativos: microcontrolador, anel NeoPixel, giroscópio
    • Conecte todos os fios positivos: microcontrolador, anel NeoPixel, giroscópio
    • Conecte fios de dados:
      • SDA e SCL do microcontrolador para o giroscópio
      • Pino D6 do microcontrolador para o anel NeoPixel
    • Verifique todas as conexões antes de alimentar
    • Opcional: use fita adesiva para fixar o suporte de pilhas na parte traseira da protoboard, tornando-o mais portátil

Passo 3: Código e Calibração

Primeiro, baixe e instale duas bibliotecas:

  1. Biblioteca Adafruit NeoPixel para controle do NeoPixel
  2. Biblioteca MPU6050 para o giroscópio

São duas ótimas bibliotecas que fazem o trabalho pesado!

Depois, baixe e instale minha biblioteca (ou copie o código 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;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, NEOPIXED_CONTROL_PIN, NEO_RBG + NEO_KHZ800);

unsigned long lastPrintTime = 0;
bool initialization = false;
uint8_t mpuIntStatus;
uint8_t devStatus;
uint16_t packetSize;
uint16_t fifoCount;
uint8_t fifoBuffer[64];
Quaternion q;
VectorFloat gravity;
float ypr[3];
volatile bool mpuInterrupt = false;

void setup() {
  Serial.begin(9600);
  Serial.println("Programa iniciado");
  initialization = initializeGyroscope();
  strip.begin();
}

void loop() {
  if (!initialization) return;
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();
  fifoCount = mpu.getFIFOCount();
  if (hasFifoOverflown(mpuIntStatus, fifoCount)) {
    mpu.resetFIFO(); return;
  }
  if (mpuIntStatus & 0x02) {
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    mpu.getFIFOBytes(fifoBuffer, packetSize);
    fifoCount -= packetSize;
    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, -MAX_ANGLE, MAX_ANGLE);
  y = constrain(y, -MAX_ANGLE, MAX_ANGLE);
  if (y < 0 && z > 0) lightLeds(y, z, 0, 5, 0, 89);
  else if (y < 0 && z < 0) lightLeds(y, z, 6, 12, 89, 0);
  else if (y > 0 && z < 0) lightLeds(y, z, 13, 19, 0, 89);
  else if (y > 0 && 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, angle);
  uint32_t color;
  for (int i = 0; i < NUM_LEDS; i++) {
    color = strip.Color(0, 0, 0);
    if (i == ledNr) color = strip.Color(0, 180, 0);
    else if (i == ledNr - 1) color = strip.Color(0, 5, 0);
    strip.setPixelColor(normalizeLedPosition(i), color);
  }
  strip.show();
}

int normalizeLedPosition(int position) {
  if (NUM_LEDS > position + LED_OFFSET) return position + LED_OFFSET;
  return position + LED_OFFSET - NUM_LEDS;
}

void printDebug(int y, int z, int lightLed, int angle) {
  if (millis() - lastPrintTime < 500) return;
  Serial.print("a="); Serial.print(angle); 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("Conexão MPU6050 bem-sucedida") : F("Falha na conexão MPU6050"));
  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 DMP (código ")); Serial.println(devStatus);
    return false;
  }
  mpu.setDMPEnabled(true);
  Serial.println(F("Habilitando detecção de interrupção (interrupção externa 0 do Arduino)..."));
  attachInterrupt(0, dmpDataReady, RISING);
  mpuIntStatus = mpu.getIntStatus();
  Serial.println(F("DMP pronto! Aguardando primeira interrupção..."));
  packetSize = mpu.dmpGetFIFOPacketSize();
  return true;
}

void dmpDataReady() { mpuInterrupt = true; }

Carregue o código: Use o adaptador FTDI para enviar o código ao Arduino.

Conecte a alimentação (pilhas)

Calibração: O mais importante é calibrar a constante "LED_OFFSET". No meu exemplo é 12. Ajuste de 0 a 23 para que, ao ligar, o LED acenda na direção em que você inclina a placa.

Para mais detalhes sobre o funcionamento, veja o próximo passo.

Passo 4: Como Funciona (Opcional)

Primeiro, sobre o giroscópio MPU6050: é um giroscópio MEMS (Sistemas Microeletromecânicos). Cada tipo tem um componente oscilante do qual se detecta aceleração e mudança de direção. Pela lei da conservação do movimento, um objeto vibrando tende a continuar no mesmo plano, e qualquer desvio vibracional deriva mudança de direção. O giroscópio contém seu próprio microcontrolador para calcular roll, pitch e yaw através de matemática complexa. Mas os dados brutos sofrem ruído e deriva, então usamos uma biblioteca externa para suavizar e obter dados limpos.

Os NeoPixels são LEDs RGB individualmente endereçáveis e encadeados em fitas e anéis. Funcionam em 5V e contêm sua própria circuitaria - apenas alimente e comunique via linha de dados única (clock + dados). A Adafruit fornece biblioteca limpa para interagir com anéis NeoPixel.

O código: Dentro de loop(), a biblioteca MPU6050_6Axis_MotionApps20 é chamada. Quando há novos dados do giroscópio, chama redrawLeds(x, y, z) com 3 argumentos representando yaw, pitch e roll.

Dentro de redrawLeds(): focamos nos eixos y, z; limitamos ambos de -MAX_ANGLE a +MAX_ANGLE (definido como 45°); dividimos 360° em 4 quadrantes e chamamos lightLeds() para cada.

Dentro de lightLeds: calculamos ângulo baseado nos dois eixos usando arco tangente; calculamos qual LED acender via função map do Arduino; resetamos a fita exceto dois LEDs (o calculado e o anterior para efeito fade); usamos normalizeLedPosition() para calibração do NeoPixel (útil pois o anel pode ser rotacionado e deve alinhar com o giroscópio); imprimimos os dois eixos, LED aceso e ângulo.

A matemática: A imagem anexada mostra o anel de LEDs e a função trigonométrica usada para determinar o ângulo.

Código Completo

Disponível em: GitHub

Esquemático

Arquivo Fritzing: sketch_gMlSrk3rCX.fzz

Processo de manufatura

  1. Construa um Jogo em Tempo Real com Giroscópio: Arduino Nano + Sensor MPU-6050
  2. Relógio de Parede Estiloso com Anel Neopixel 60 LEDs Adafruit e Arduino
  3. Sensor K30 CO₂: Monitoramento de Qualidade do Ar Interno em Tempo Real
  4. Facilitando Comunicação Surdo-Cego com 1Sheeld e Arduino
  5. Controle USB para Jogos DIY com Arduino – Construa Seu Próprio Gamepad de Alto Desempenho
  6. Mealheiro Inteligente: Controlar Aceitador de Moedas com Arduino Nano
  7. Pixie: Relógio de Pulso NeoPixel Baseado em Arduino – Elegante Timepiece DIY LED
  8. Controlar um LED via Bluetooth com Arduino – Guia DIY Simples
  9. Integrando Sensor de Impressão Digital Capacitivo DFRobot com Arduino ou ESP8266
  10. Dominando Reconhecimento e Síntese de Fala no Arduino Due