El dispositivo cuenta con un sensor ultrasónico para medir la distancia al objeto más cercano, un acelerómetro para medir el ángulo con respecto al suelo, una pantalla LCD para mostrar los resultados y un PCB diseñado a medida en el que están conectados todos los componentes.

Podemos operar el dispositivo con un solo botón. Una vez que alimentamos el dispositivo, debemos seleccionar la unidad de medida.

Pulsando el botón podemos alternar entre las unidades, y si mantenemos pulsado el botón durante un rato entraremos en el primer programa. Aquí podemos medir la distancia y también tenemos la capacidad de almacenar las dos últimas medidas.

Para entrar en el segundo programa, nuevamente tenemos que presionar y mantener presionado el botón por un tiempo. En este programa podemos medir un área cuadrada tomando dos medidas de distancia perpendiculares.

El siguiente programa es el nivel de burbuja digital y aquí podemos medir el ángulo con respecto al suelo.

Usando el botón podemos alternar entre los dos ejes o podemos medir el Pitch o el Roll.

Esquema del circuito del medidor de rango de Arduino

Aquí está el esquema del circuito de este proyecto de Arduino.


Componentes necesarios 

  • Sensor ultrasónico HC-SR04
  • Acelerómetro de giroscopio de 3 ejes MPU6050
  • LCD de 16 × 2 caracteres
  • Arduino Nano
  • Cables para conexión
  • Batería 9v
  • Protoboard
  • Resistencia 1k
  • Resistencia 220 ohmios

Montaje del dispositivo

Sin embargo, después de varios días han llegado los PCB. La calidad de los PCB es excelente y todo es exactamente igual que en el diseño.

Bien, ahora podemos comenzar a ensamblar la electrónica para este proyecto. Comencé soldando los encabezados de los pines en la PCB. De esta forma podemos conectar y desconectar fácilmente los componentes cuando sea necesario.

Luego inserté y soldé las tres resistencias. Dos de ellos son para el divisor de voltaje para el contraste de LCD. La resistencia de 1k debe colocarse en R1 y la de 220 ohmios en R2. El tercero es una resistencia pull-up para el botón.

Entonces, primero debemos incluir la biblioteca Wire.h para la comunicación I2C del acelerómetro, así como la biblioteca LiquidCrystal.h para controlar la pantalla LCD. Luego, necesitamos definir la pantalla LCD, la dirección I2C del módulo acelerómetro MPU6050 , los pines del sensor ultrasónico, así como algunas variables necesarias para el programa a continuación.

#include <Wire.h> // Biblioteca de comunicación I2C
#include <LiquidCrystal.h> // incluye la biblioteca LiquidCrystal
LiquidCrystal lcd ( 7, 6, 5, 4, 3, 2 ) ; // Crea un objeto LCD. Parámetros: (rs, enable, d4, d5, d6, d7)
const int MPU = 0x68 ; // Dirección I2C del acelerómetro MPU6050 
#define trigPin 8
#define echoPin 9
#define selectButton 10
int16_t AcX, AcY, AcZ;
larga duración;
distancia de flotación ;
int programa = 0;
flotar d = 0;
flotador d1 = 0;
flotador d2 = 0;
área flotante = 0;
int eje = 0;
int ángulo = 0;
int unitSelect = 0;
Unidad de cadena = "cm" ;

En la sección de configuración, necesitamos inicializar tanto la interfaz I2C del acelerómetro como la pantalla de cristal líquido, así como definir los modos de pin para el disparador del sensor ultrasónico y los pines de eco, y el pin del botón.

configuración vacía () {  
  // Inicializar la interfaz al MPU6050
  Cable. comenzar () ;
  Cable. beginTransmission ( MPU ) ;
  Cable. escribir ( 0x6B ) ;
  Cable. escribir ( 0 ) ;
  Cable. endTransmission ( verdadero ) ;
  lcd. comenzar ( 16, 2 ) ; // Inicializa la interfaz a la pantalla LCD
  
  pinMode ( trigPin, SALIDA ) ;
  pinMode ( echoPin, INPUT ) ;
  pinMode ( selectButton, INPUT_PULLUP ) ;
}

En la sección del bucle principal tenemos unas sentencias de cambio a través de las cuales podemos alternar entre los diferentes programas de nuestro dispositivo. En el primero, o caso número 0, seleccionamos la unidad de medida. Usando la función lcd.print () imprimimos el texto en la pantalla LCD y usando las declaraciones if alternamos entre las cuatro unidades de medida.

cambiar ( programa ) { // Cambiar entre diferentes programas   
    caso 0: // Seleccionar unidad de medida
      lcd. setCursor ( 0, 0 ) ; // Establece la ubicación en la que se mostrará el texto subsiguiente escrito en la pantalla LCD
      lcd. imprimir ( "Seleccionar unidad:" ) ;
      lcd. setCursor ( 13, 0 ) ;
      lcd. imprimir ( unidad ) ;
      lcd. imprimir ( "" ) ;
      retraso ( 10 ) ;
      // Si se presiona el botón - cambiar unidad
      if ( digitalRead ( selectButton ) == 0 ) {  
        if ( unitSelect == 0 ) {  
          unidad = "en" ;
          unitSelect = 1;
        }
        else if ( unitSelect == 1 ) {   
          unidad = "m" ;
          unitSelect = 2;
        }
        else if ( unitSelect == 2 ) {   
          unidad = "pies" ;
          unitSelect = 3;
        }
        else if ( unitSelect == 3 ) {   
          unidad = "cm" ;
          unitSelect = 0;
        }
        // Si el botón se mantiene presionado por más de medio segundo, cambie el programa
        retraso ( 500 ) ;
        if ( digitalRead ( selectButton ) == 0 ) {  
          programa = 1;
          lcd. claro () ;
          retraso ( 500 ) ;
        }
      }
      romper ;

Debemos notar aquí que la variable unitSelect toma acción en la función cunstom getDistance (), donde en realidad dice a qué unidad debemos convertir la unidad cm básica que obtenemos del sensor ultrasónico.

/ Conversión de unidades
  if ( unitSelect == 1 ) {  
    distancia = distancia; // cm a cm
    unidad = "cm" ;
  }
  else if ( unitSelect == 2 ) {   
    distancia = distancia *   0.393701 ; // cm a in
    unidad = "en" ;
  }
  else if ( unitSelect == 3 ) {   
    distancia = distancia * 0.01 ; // cm am
    unidad = "m" ;
  }
  else if ( unitSelect == 0 ) {   
    distancia = distancia * 0.0328 ; // cm a pies
    unidad = "pies" ;
  }

Para poder seleccionar la unidad de medida y entrar también en el primer programa del dispositivo solo tenemos que mantener pulsado el pulsador durante más de medio segundo.

// Si el botón se mantiene presionado por más de medio segundo, cambie el programa
        retraso ( 500 ) ;
        if ( digitalRead ( selectButton ) == 0 ) {  
          programa = 1;
          lcd. claro () ;
          retraso ( 500 ) ;
        }
      }
      romper ;

En el caso número 1 o en el programa de medición de distancia, primero obtenemos la distancia al objeto más cercano usando la función personalizada getDistance ().

caso 1:   // Programa de medición de distancia
      distancia = getDistance () ; // Distancia al objeto más cercano
      lcd. setCursor ( 0, 0 ) ;
      lcd. imprimir ( "Dist:" ) ;
      lcd. imprimir ( distancia ) ; // Imprime el valor de la distancia desde el sensor
      lcd. imprimir ( "" ) ;
      lcd. setCursor ( 14, 0 ) ;
      lcd. imprimir ( unidad ) ;
      retraso ( 10 ) ;
      lcd. setCursor ( 0, 1 ) ;
      lcd. imprimir ( "d:" ) ;
      lcd. setCursor ( 8, 1 ) ;
      lcd. imprimir ( "d:" ) ;
      retraso ( 200 ) ;
      // Guardar distancia 1
      if ( digitalRead ( selectButton ) == 0 ) {  
        si ( d == 0 ) {  
          lcd. setCursor ( 0, 1 ) ;
          lcd. imprimir ( "d:" ) ;
          lcd. setCursor ( 2, 1 ) ;
          lcd. imprimir ( distancia ) ;
          d = 1;
          retraso ( 100 ) ;
        }
        // Guardar distancia 2
        más si ( d == 1 ) {   
          lcd. setCursor ( 8, 1 ) ;
          lcd. imprimir ( "d:" ) ;
          lcd. setCursor ( 10, 1 ) ;
          lcd. imprimir ( distancia ) ;
          d = 0;
          retraso ( 100 ) ;
        }
        // Si el botón se mantiene presionado más de medio segundo, cambie el programa
        retraso ( 500 ) ;
        si ( digitalRead ( selectButton ) == 0 ) { 
          programa = 2;
          d = 0;
          lcd.claro () ;
          retrasar( 500 ) ;
        }
      }
      romper ;

Veamos cómo funciona esta función.

// ===== getDistance - Función personalizada
flotar getDistance () {  
  // Borra el trigPin
  digitalWrite ( trigPin, LOW ) ;
  // Establece el trigPin en estado ALTO durante 10 microsegundos
  digitalWrite ( trigPin, HIGH ) ;
  delayMicroseconds ( 10 ) ;
  digitalWrite ( trigPin, LOW ) ;
  // Lee el echoPin, devuelve el tiempo de viaje de la onda de sonido en microsegundos
  duración = pulseIn ( echoPin, HIGH ) ;
  // Calculando la distancia
  distancia = duración * 0.034 / 2; // distancia en cm
  
  // Conversión de unidades
  if ( unitSelect == 1 ) {  
    distancia = distancia; // cm a cm
    unidad = "cm" ;
  }
  else if ( unitSelect == 2 ) {   
    distancia = distancia *   0.393701 ; // cm a in
    unidad = "en" ;
  }
  else if ( unitSelect == 3 ) {   
    distancia = distancia * 0.01 ; // cm am
    unidad = "m" ;
  }
  else if ( unitSelect == 0 ) {   
    distancia = distancia * 0.0328 ; // cm a pies
    unidad = "pies" ;
  }
  distancia de regreso ;
}

Aquí, usando el pasador de disparo, le decimos al sensor que genere una onda de sonido ultrasónica.

Luego, usando el pin de eco y la función pulseIn (), medimos la duración de la onda que viajó desde el sensor hasta el objeto y viceversa. Teniendo en cuenta la velocidad del sonido y el tiempo de viaje, podemos calcular fácilmente la distancia. Entonces imprimimos la distancia medida junto con algo de texto en la pantalla LCD y usando las declaraciones «si», si presionamos el botón, imprimimos o guardamos las dos últimas medidas.

El siguiente es el programa para calcular el área en el que estamos usando métodos similares. Necesitamos tomar dos medidas perpendiculares y simplemente multiplicarlas para obtener el área del cuadrado que forman.

caso 2:   // Programa de medición de área
      distancia = getDistance () ;
      lcd. setCursor ( 0, 0 ) ;
      lcd. imprimir ( "Área:" ) ;
      lcd. imprimir ( área ) ; // Imprime el área calculada a partir de las dos medidas
      lcd. setCursor ( 12, 0 ) ;
      lcd. imprimir ( unidad ) ; // Imprime la unidad seleccionada y el signo cuadrado debajo
      lcd. imprimir ( "^ 2" ) ;
      retraso ( 200 ) ;
      si ( d == 0 ) {  
        lcd. setCursor ( 0, 1 ) ;
        lcd. imprimir ( "d1:" ) ;
        lcd. setCursor ( 3, 1 ) ;
        lcd. imprimir ( distancia ) ;
        retraso ( 200 ) ;
      }
      más si ( d == 1 ) {   
        lcd. setCursor ( 9, 1 ) ;
        lcd. imprimir ( "d2:" ) ;
        lcd. setCursor ( 12, 1 ) ;
        lcd. imprimir ( distancia ) ;
        retraso ( 200 ) ;
      }
      más si ( d == 2 ) {   
        lcd. setCursor ( 6, 0 ) ;
        lcd. imprimir ( área ) ;
        retraso ( 200 ) ;
      }
      // Guardar distancia 1
      if ( digitalRead ( selectButton ) == 0 ) {  
        si ( d == 0 ) {  
          lcd. setCursor ( 0, 1 ) ;
          lcd. imprimir ( "d1:" ) ;
          lcd. setCursor ( 3, 1 ) ;
          lcd. imprimir ( distancia ) ;
          d = 1;
          d1 = distancia;
          retraso ( 100 ) ;
        }
        // Guardar distancia 2
        más si ( d == 1 ) {   
          lcd. setCursor ( 9, 1 ) ;
          lcd. imprimir ( "d2:" ) ;
          lcd. setCursor ( 12, 1 ) ;
          lcd. imprimir ( distancia ) ;
          d = 2;
          d2 = distancia;
          área = d1 * d2; // Calcula el área
          retraso ( 100 ) ;
        }
        más si ( d == 2 ) {   
          lcd. claro () ;
          d = 0;
          área = 0;
          retraso ( 100 ) ;
        }
        // Si el botón se mantiene presionado más de medio segundo, cambie el programa
        retraso ( 500 ) ;
        if ( digitalRead ( selectButton ) == 0 ) {  
          programa = 3;
          d = 0;
          lcd. claro () ;
          retraso ( 500 ) ;
        }
      }
      romper ;

El último caso es el programa de medición de ángulos. Aquí necesitamos leer los datos del acelerómetro, que en realidad es la fuerza del campo gravitacional de la Tierra en tres ejes diferentes, X, Y y Z. El valor de cada eje se almacena en 2 registros, por lo que necesitamos leer un total de 6 registros. y combinarlos para obtener el valor correcto.

caso 3:    // Programa de medición de ángulos
      // Leer los datos del acelerómetro
      Cable. beginTransmission ( MPU ) ;
      Cable. escribir ( 0x3B ) ; // Comenzar con el registro 0x3B (ACCEL_XOUT_H)
      Cable. endTransmission ( falso ) ;
      Cable. requestFrom ( MPU, 6, verdadero ) ; // Leer 6 registros en total, cada valor de eje se almacena en 2 registros
      AcX = Alambre. leer () << 8 | Cable. leer () ; // valor del eje X 
      AcY = Alambre. leer () << 8 | Cable. leer () ; // Valor del eje Y 
      AcZ = Alambre. leer () << 8 | Cable. leer () ; // Valor del eje Z 
     
      si ( eje == 0 ) {  
        // Calcular el ángulo de inclinación (rotación alrededor del eje Y)
        ángulo = atan ( -1 * AcX / sqrt ( pow ( AcY, 2 ) + pow ( AcZ, 2 ))) * 180 / PI;
        lcd. setCursor ( 0, 0 ) ;
        lcd. imprimir ( "Pitch" ) ;
      }
      else if ( eje == 1 ) {   
        // Cálculo del ángulo de balanceo (rotación alrededor del eje X)
        ángulo = atan ( -1 * AcY / sqrt ( pow ( AcX, 2 ) + pow ( AcZ, 2 ))) * 180 / PI;
        lcd. setCursor ( 0, 0 ) ;
        lcd. imprimir ( "Rollo" ) ;
      }
      lcd. setCursor ( 0, 1 ) ;
      lcd. print ( "Ángulo:" ) ;
      lcd. print ( abs ( ángulo )) ;
      lcd. imprimir ( "" ) ;
      lcd. setCursor ( 10, 1 ) ;
      lcd. print ( "deg" ) ;
      retraso ( 200 ) ;
      // Cambiar eje
      if ( digitalRead ( selectButton ) == 0 ) {  
        si ( eje == 0 ) {  
          eje = 1;
          retardo (100 ) ;
        }
        // Guardar distancia 2
        más si ( eje == 1 )   {
          eje = 0;
          retraso ( 100 );
        }
        // Si el botón se mantiene presionado más de medio segundo, cambie el programa
        retraso ( 500 );
        if ( digitalRead ( selectButton ) == 0 )  {
          programa = 0;
          lcd. claro ();
          retraso ( 500 );
        }
      }
      romper ;

Una vez que tengamos los valores X, Y y Z del acelerómetro, podemos calcular el ángulo de inclinación o rotación alrededor del eje Y, así como el ángulo de balanceo o rotación alrededor del eje X, usando las dos ecuaciones. 

howtomechatronics.com