Vehículo de robot con control de Blynk y odometría.

Bienvenido a un nuevo blog de nuestra serie sobre Coches Robot. Esta vez se trata de determinar la distancia recorrida con la ayuda del número de revoluciones de las ruedas. Este método se denomina odometría. Eso proviene del griego y significa la medición de la distancia.

Fundamentos geométricos

Para conducir en línea recta, esto es bastante sencillo. Si ambas ruedas giran a la misma velocidad, la distancia recorrida tras una revolución es igual a la circunferencia de la rueda, es decir, con diámetro d

Las revoluciones se pueden determinar con un disco ranurado y un sensor fotoeléctrico en forma de horquilla. Si el disco de la ranura tiene n ranuras, obtendremos n impulsos por revolución. Para determinar la distancia entre dos pulsos, debemos dividir la circunferencia entre los pulsos por revolución. Obtenemos el factor distancia.

Además, la determinación del ángulo de giro también es sencilla para un vehículo de dos ruedas si se supone que ambas ruedas giran en sentidos opuestos a la misma velocidad. En este caso, ambas ruedas describen un círculo alrededor del punto de vista invariable con la distancia de la rueda a como diámetro. Para girar el vehículo en 360 grados, se necesita una distancia de

puede ser cubierto. Para un ángulo α se obtiene una distancia de

Ambas ruedas recorren la misma distancia, pero en direcciones opuestas. Para obtener el número de pulsos, hay que dividir por el factor de distancia.

El recíproco da como resultado el factor angular en grados / pulso

geometría

Hardware requerido

A diferencia de la primera parte, en este caso necesitamos el módulo ESP32, porque se necesitan entradas adicionales para las barreras de la luz de la horquilla. También es mejor utilizar el chasis de la impresora 3D, ya que así es mucho más fácil montar las barreras de luz de la horquilla.

Número

Componente

Nota

1

2 Motores con ruedas


1

Bola de rodamiento


6

Tornillos m3 x 30 con madre


2

Tornillos m3 x 12 con madre


1

Chasis de la impresora 3D


1

Titular de PowerPack de la impresora 3D


1

D1 Board NodeMCU ESP8266MOD-12F


1

Set Sensor medición de velocidad con arandelas de ranura


2

Tornillos de estaño 2.2 x 6,5 mm.



Para utilizar el escudo del controlador del motor con los controladores ESP, son necesarias pequeñas modificaciones, ya que los controladores ESP funcionan con un voltaje de funcionamiento de 3,3V.

Desde el pin D7 se debe conectar una resistencia de 10 kOhm a GND. Esto es necesario porque el pin D7 de la pantalla está conectado a 5V a través de una resistencia de pullup de 10 kOhm.

Escudo de conductor de motorLas conexiones A0 a A5, así como las conexiones de alimentación correspondientes, deben estar equipadas con cabezales de pines. Para que estas conexiones se usen para los sensores, el voltaje de alimentación también debe conectarse en lugar de 5V a 3.3 V. Esto se hace simplemente cortando el cable de conexión a los pines de la parte inferiores. Entonces, puede conectar los pines al pin de 3,3V. Las conexiones para el voltaje de alimentación también deben estar equipadas.

Para conectar los dos motores se utilizan las salidas M2 y M4. Las conexiones del motor se conectan a los terminales de tornillo correspondientes en el escudo del motor. Si el vehículo se suministra a través de la toma USB del microcontrolador, el puente (círculo rojo) se debe retirar y conectar la entrada M + a la conexión de 5V del microcontrolador (se muestra en verde en la figura).

Motores en el protector del conductor.

Para la medición de la velocidad de rotación, se coloca una arandela de ranura en el extremo interno de cada eje del motor y se atornillan las barreras luminosas en forma de horquilla al soporte previsto para ello con un tornillo autorroscante. 

Rebanadas de ranura

Ahora conecta VCC, GND y D0 mediante un cable tripolar a las conexiones A2 y A3 del escudo del motor. VCC con + 5V, GND con GND y D0 con A2 o A3.

Motorshield

A continuación, el escudo motor se conecta simplemente a la placa del microcontrolador. No son necesarias más medidas de cableado.
Para la fijación mecánica de las placas, el chasis de la impresora 3D tiene los agujeros correspondientes, a los que se puede atornillar la placa del microcontrolador con espaciadores. Con el kit es posible que tenga que perforar agujeros adecuados.

Software

Para el control remoto del vehículo, se debe utilizar el software gratuito disponible Blynk. Blynk es un proyecto de Kickstarter que permite el control más simple de los microcontroladores con un teléfono inteligente. Elemento esencial es la aplicación con la que se puede crear una aplicación a través de un tipo de kit de construcción. Toda la información sobre esta aplicación se almacena en el servidor Blynk. Cada aplicación recibe un número de identificación único. En el lado del microcontrolador, una librería garantiza que el microcontrolador se comunique con el servidor Blynk y que la aplicación en el teléfono inteligente pueda leer o controlar directamente los pines del microcontrolador. No se requiere más programación en el microcontrolador. La única condición es que el microcontrolador debe tener acceso al servidor Blynk. Dado que no se puede controlar los pines del microcontrolador directamente para el control remoto del vehículo, será necesaria una pequeña programación.

Primero, sin embargo, la aplicación Blynk debe estar instalada en el teléfono inteligente. Después de que la aplicación se haya instalado y comience, aparece la pantalla de inicio de sesión. Para usar Blynk, necesita una cuenta para el servidor Blynk. Esto requiere solo una dirección de correo electrónico y cualquier contraseña.

Después de crear una cuenta, aparece un mensaje sobre la energía. Para crear un proyecto Blynk, necesita una cierta cantidad de energía para cada elemento de pantalla. Con una nueva cuenta, obtendrá automáticamente 2000 puntos de alimentación con los que puede trabajar. Si necesita más puntos de energía para un proyecto, puede comprarlos.

Después de esta ventana de mensajes, aparece la pantalla de inicio. Aquí, el proyecto Coche robot ahora se puede cargar a través del siguiente código QR.

Ahora veas la ventana del proyecto. Si hace clic en el símbolo de la tuerca, se abre la configuración del proyecto. En la configuración del proyecto encontrará el enlace "Email all". Cuando hace clic en él, recibirá un correo electrónico con la clave de que su microcontrolador necesita sketch para comunicarse con el servidor Blynk. Con el icono del triángulo en la ventana del proyecto en la parte superior derecha, inicia la aplicación.

Aplicación de blync

Más información sobre Blynk, se puede encontrar en Internet o en Libro Smarthome. El libro también describe cómo instalar su propio servidor privado Blynk en un Raspberry Pi.

El control se realiza configurando la ruta deseada y el ángulo deseado. Al hacer clic en los botones hacia adelante o hacia atrás, el vehículo recorre la distancia establecida. Al hacer clic en los botones de la izquierda o hacia la derecha, el vehículo gira en el ángulo establecido.

Si hace clic en el botón Aprender, luego cambia al modo de aprendizaje. Cada comando ingresado ahora está grabado y se puede realizar automáticamente más tarde. Recientemente, haga clic en el botón Aprender, finaliza el modo de aprendizaje. Ahora puede ejecutar automáticamente los comandos almacenados haciendo clic en el botón Ejecutar.

En la parte inferior, se muestra tantas líneas de comando se almacenaron. Se pueden almacenar un máximo de 30 líneas de comando. Al cambiar al modo de aprendizaje, el contador de la línea de comandos se restablece a 0.

El Sketch

Además del paquete ESP32, necesita la librería Blynk que se puede instalar a través de la administración de la librería.

 #include 
 #include
 
 // Debe obtener un token de autenticación en la aplicación Blynk. // Ir a la configuración del proyecto (icono de tuerca).
 
 // Tecla de autenticación de Blynk
 #define auth "*********************************"
 // ssid de tu wlan
 #define ssid "*******************************"
 // Passkey para tu WLAN
 #define pase "*************************************"
 // Nombre del servidor privado Blynk, o "" Si usa el servidor público de Blynk
 #define srv "raspberrypi4"
 
 
 #define maxcommands 30 // anzahl der befehlszeileilen, die gespeichert werden können
 
 #define blynk_print serial
 
 // bits im schieberegister zu motor zuordnung
 #define m1a 2 // motor1 a
 #define m1b 3 // motor1 b
 #define m2a 1 // motor2 a
 #define m2b 4 // motor2 b
 #define m3a 5 // motor3 a
 #define m3b 7 // motor3 b
 #define m4a 0 // motor4 a
 #define m4b 6 // motor4 b
 
 // pins für das drehrichtungs schieberegister
 #define shift_in 12 // Dateneingang Arduino D8
 #define shift_clk 17// schiebetackt arduino d4
 #define latch_clk 19 // Speichertakt Arduino D12
 #define out_enable 14// MIT Low Ausgang Aktivieren Arduino D7
 
 // pwm für motoren geschwindigkeit zwischen 0 und 1023
 #define m1pwm 23 // Pin Für Motor1 Arduino D11
 #define mright 25// Pin Für Motor2 Arduino D3
 #define m3pwm 27 // Pin Für Motor3 Arduino D6
 #define mleft 16 // PIN FUR MOTOR4 Arduino D5
 
 // servo anschlüsse
 #define servo1 5// PIN FÜR SERVO1 D10
 #define servo2 13 // PIN FUR SERVO2 D9
 
 // motor zuordnung
 #define DAY 2
 #define dleft 4
 
 // konstanten für drehrichtung
 #define stop 0
 #define hacia adelante 1
 #define hacia atrás 2
 
 #define speedleft 35
 #define speedright 34
 
 // Aktueller Inhalt des Richtungs-SchieBereGisters
 uint32_t direcciones = 0;
 
 Typedef
 estructura {
   carbonizarse cmd;
   uint16_t Val;
 } Cmdline;
 
 Cmdline comandos[Maxcommands];
 uint8_t cmdcnt = 0;
 
 int32_t cn s = 0;
 int32_t centa = 0;
 uint16_t strecke = 0;
 uint16_t winkel = 0;
 booleano botón = 0;
 flotador winkelfaktor, streckenfaktor;
 booleano aprendiendo = falso;
 booleano programa = falso;
 uint8_t PRGSTEP;
 
 // für interrumpir la sincronización
 PORTMUX_TYPE izquierdmux = Portmux_Initializer_Unlocked;
 PORTMUX_TYPE RightMux = Portmux_Initializer_Unlocked;
 
 
 // Rutina de servicio de interrupción Für Enlay SpeedSensor
 vacío Iram_attr isrilla() {
   PORTENTER_CRÍTICO(&izquierdmux);
   cn s--;
   Portexit_crítico(&izquierdmux);
   Si ((cn s <= 0) && (centa<=0)) {
     motores(0,0);
     Si (programa) próximo paso();
  }
 }
 
 // Rutina de servicio de interrupción Für Rechen SpeedSensor
 vacío Iram_attr isrright() {
   PORTENTER_CRÍTICO(&RightMux);
   centa--;
   Portexit_crítico(&RightMux);
   Si ((cn s <= 0) && (centa<=0)) {
     motores(0,0);
     Si (programa) próximo paso();
  }
 }
 
 
 
 // füllt das schieberegister zur motoresteuerung
 // mit dem Inhalt von direcciones
 vacío Senddirections() {
   uint8_t I;
   escritura digital(Latch_clk, BAJO);  // SPEICHER SPERREN
   escritura digital(DESPLAZAR EN, BAJO);   // eingang auf 0
   por (I=0; I<8; I++) {
     escritura digital(Shift_clk, BAJO);// bit für bit einlesen
     Si (direcciones & un poco(7-I)) {
       escritura digital(DESPLAZAR EN, ELEVADO);
    } demás {
       escritura digital(DESPLAZAR EN, BAJO);
    }
     escritura digital(Shift_clk, ELEVADO);
  }
   escritura digital(Latch_clk, ELEVADO); // mit der positiven flanke speichern
 }
 
 vacío próximo paso() {
   Si (PRGSTEP < cmdcnt) {
      cambiar (comandos[PRGSTEP].cmd) {
        caso 'F' :
        caso 'B' : manejar(comandos[PRGSTEP].cmd,comandos[PRGSTEP].Val);
               rotura;
        caso 'L' :
        caso 'R' : turno(comandos[PRGSTEP].cmd,comandos[PRGSTEP].Val);
               rotura;
      }
      PRGSTEP++;
  } demás {
     programa = falso;
  }
 }
 
 // die drehrichtung für einen motor festplegen
 vacío SetDirección(uint8_t motor, uint8_t dirección) {
   uint8_t a=0, B=0;
   // Bitnummern Für Den Gewählten Motor Bestimmen
   cambiar (motor) {
     caso 1: a=M1A; B=M1b; rotura;
     caso 2: a=M2a; B=M2b; rotura;
     caso 3: a=M3A; B=M3b; rotura;
     caso 4: a=M4A; B=M4b; rotura;
  }
   // Primero ponga ambos bits para el motor a 0 significa parada
   Direcciones &= ~ un poco(a) & ~ un poco(B);
 
   cambiar (dirección) {
     cubo Hacia adelante: Direcciones |= un poco(a); rotura; // para el bit hacia adelante de A a 1
     cubo Hacia atrás: Direcciones |= un poco(B); rotura;// para bit b hacia atrás b en 1
  }
   //Serial.printf ("direcciones =% x \ n", direcciones);
   Senddirections(); // enviar nueva configuración al registro de desplazamiento
 }
 
 
 //Velocidad
 En t Z;
 
 
 vacío motor(Int16_t izquierda, Int16_t Derecha) {
   //Serial.printf( "Links% I, Derecho% I \ N ", izquierda, derecha);
   //Dirección
   SI (izquierda<0) {
     SetDirección(Diario,Hacia atrás);
  } Demás SI (izquierda == 0){
     SetDirección(Diario,DETENER);
  } Demás {
     SetDirección(Diario,Hacia adelante);
  }
   SI (Derecha<0) {
     SetDirección(Drick,Hacia atrás);
  } Demás SI (Derecha == 0){
     SetDirección(Drick,DETENER);
  } Demás {
     SetDirección(Drick,Hacia adelante);
  }
   //Velocidad
   Ledcwrite(Diario,Sección(izquierda));
   Ledcwrite(Drick,Sección(Derecha));
 }
 
 vacío manejar(Carbonizarse dirección, uint16_t Val) {
   SI (aprendiendo) {
     SI (Cmdcnt < Maxcommands) {
       comandos[Cmdcnt].Cmd = dirección;
       comandos[Cmdcnt].Val = Val;
       Cmdcnt++;
    }
  } Demás {
     cn s = Val;
     centa = Val;
     SI (dirección == 'F') {
       motor(Z,Z);
    } Demás {
       motor(-Z,-Z);
    }
  }      
 }
 
 vacío turno(Carbonizarse dirección, uint16_t Val) {
   SI (aprendiendo) {
     SI (Cmdcnt < Maxcommands) {
       comandos[Cmdcnt].Cmd = dirección;
       comandos[Cmdcnt].Val = Val;
       Cmdcnt++;
    }
  } Demás {
     cn s = Val;
     centa = Val;
     SI (dirección == "L ') {
       motor(-Z,Z);
    } Demás {
       motor(Z,-Z);
    }
  }      
 }
 
 vacío configurar() {
   De serie.Empezar(115200);
   De serie.Prender();
   De serie.Prender("Inicialización");
   // Poner todos los pasadores utilizados como salida
   mono(Desplazar en,PRODUCCIÓN);
   mono(Shift_clk,PRODUCCIÓN);
   mono(Latch_clk,PRODUCCIÓN);
   mono(OUT_ENABLE,PRODUCCIÓN);
   Ledcsetup(Diario, 100, 10);
   Ledcsetup(Drick,100, 10);
   ledcattachpin(Melancólico,Diario);
   ledcattachpin(Mright,Drick);
   // Todos los motores paran
   Direcciones = 0;
   // calcular los parámetros de odometría
   // Factor de estiramiento = Diámetro de la rueda * pi / number_schlitze
   factor estirado = 67 * 3.14 /20; // = 10.524 mm / pulso
   // factor de ángulo = 360 grados / (distancia del eje * pi) * Factor de estiramiento
   factor de ángulo = (360 * 67)/(130 * 20); // = 9,277 grado / pulso
   Senddirections();  // enviar al cambio de registro
   escritura digital(OUT_ENABLE,0); // Salidas de liberación del registro de turnos
   Z=1023;
   mono(Time,Aporte);
   mono(SpeedRight,Aporte);
   cn s=0;
   centa=0;
   Ruptura de adjuntos(Time,Isrilla,Descendente);
   Ruptura de adjuntos(SpeedRight,Isrright,Descendente);
   
 
   De serie.Prender("Iniciar Blynk");
   #Ifdef srv
     Blenk.Empezar(Auténtico, Ssid, PASAPORTE, Srv, 8080);
   #else
     Blenk.Empezar(Auténtico, Ssid, PASAPORTE);
   #endif
   botón = 0;
 }
 
 // bucle de prueba pequeño
 vacío círculo() {
     Blenk.correr();
 }
 
 Blynk_write(V0)
    { ruta = param[0].asine(); }
 Blynk_write(V1)
    { ángulo = param[0].asine(); }
 Blynk_write(V2)
 { SI (param[0].asine() == 0) {
       botón = falso;
    } Demás {
         SI (!botón) {
             botón = cierto;
             manejar('F',ruta / factor estirado);
        }
    }
 }
   
 Blynk_write(V3)
 { SI (param[0].asine() == 0) {
       botón = falso;
    } Demás {
         SI (!botón) {
             botón = cierto;
             manejar("B ',ruta /factor estirado);
        }
    }
 }
 Blynk_write(V4)
 { SI (param[0].asine() == 0) {
       botón = falso;
    } Demás {
       SI (!botón) {
         botón = cierto;
         turno("L ',ángulo / factor de ángulo);
      }
    }
 }
 Blynk_write(V5)
 { SI (param[0].asine() == 0) {
     botón = falso;
    } Demás {
         SI (!botón) {
             botón = cierto;
             turno("R ',ángulo /factor de ángulo);
        }
    }
 }
 
 Blynk_write(V6)
 {
     SI (!aprendiendo) {
         PRGSTEP=0;
         programa = cierto;
         Próximo paso();
    }
 }
 
 Blynk_write(V7)
 {
     aprendiendo = (param[0].asine() != 0);
     SI (aprendiendo) Cmdcnt = 0;
 }
 
 Blynk_read(V8)
 {
     Blenk.lejano virtual(V8,Cmdcnt);
 }

Código fuente como descarga

Diviértase con el coche robot!


Esp-32Proyectos para principiantes

2 comentarios

Gerald Lechner

Gerald Lechner

Wenn in Zeile 72 und 73 die Strecke auf 300 und der Winkel auf 90 voreingestellt werden, dann stimmen die Werte nach dem Start mit den Schiebern in der Blynk-App überein. Das Problem mit der Verbindung kommt daher, dass das Board eine relativ schlechte Wlan Empfindlichkeit hat

Walter

Walter

Sehr schönes Projekt, und einfacher als erst gedacht. Vor allem die Odometrie ist so ein Kinderspiel.
Umgesetzt mit ein ESP32 Dev Board, motordriver L289N und lokalen Blynkserver.

Ein offenes Problem ist, dass der Blynkserver keine initiale Werte gibt ( oder ich nicht weis wie ). Was bedeutet das erst die Schieber für Distanz und Winkel betätigt werden müssen, sonst ist der Wert der den man im Programm festlegt ( = 0 und dann passiert nichts ).
Der Blynkserver ist für mich sowie so eine Blackbox, wobei manchmal keine Verbindung zu Stande kommt, scheinbar ohne Ursache. Nach einigen Reboots funktioniert es dann auf einmal .

Deja un comentario

Todos los comentarios son moderados antes de ser publicados

Artículos de blog

  1. Ahora instalamos el esp32 a través de la administración.
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. Transporte Aéreo - programación de ESP mediante redes locales inalámbricas