Coche RC con NodeMCU (ESP8266)

Introducción

Materiales utilizados

  • Coche RC
  • NodeMCU V1(ESP8266)
  • Puente H (L293D)
  • ProtoBoard y jumpers

Introducción

LA idea es convertir un coche RC para que sea manejado por un ESP8266, creo que es el primer coche controlado por websocket, al menos no he visto otro en lo que buscaba información para este proyecto.

El coche lo compre el mas barato que encontré y al desarmarlo tenia dos motores DC 5V uno para el impulso y otro para la dirección, mas adelante les explicare el problema que tuve para el control de la dirección.
Tuve mucho interés en el manejo de los websockets que son los sustitutos del GET y POST en HTTP y los mas idoneos para este tipo de comunicación el cual estan siempre conectados cliente/servidor
El coche se conectara a mi red WIFII y estará funcionando como server, a la espera de que se conecten los clientes, que podrán ser un movil, tablet, PC, por medio de un browser a través de HTML.

El HTML consistirá en 5 botones básicos arriba, abajo, izquierda, derecha, parada, a los que le doy algo de estilo con CSS, demostrando así el enorme potencial de estos modulos ESP8266.

Primera Demo

Pasos:

1-paso: Abrir el coche y quitar la parte de radiofrecuencia el mando tampoco nos serviría, lo pueden guardar para otro proyecto tanto el mando como el transmisor
2-paso: conectar los motores al puente H

Para mas información de que es un puente H:

http://panamahitek.com/el-puente-h-invirtiendo-el-sentido-de-giro-de-un-motor-con-arduino/

3-paso asignar pines del ESP8266 y conectar

const byte AcelMotor_pin = 14;  // Pin D5, to H-Brige "enable 1"
const byte Adelante_pin = 12;   // Pin D6, to H-Brige "input 1"
const byte Atras_pin = 13;      // Pin D7, to H-Brige "input 2"

const byte Derecha_pin = 4;     // Pin D2, to H-Brige "input 1"
const byte Izquierda_pin = 5;   // Pin D1, to H-Brige "input 2"
Asignacion de pin

 


 

 

Empezamos con la adaptación!

 

El codigo

Lo primero es instanciar al websocket y preparar el modulo como server

ESP8266WiFiMulti WiFiMulti;
ESP8266WebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(81);

Iniciamos la coneccion a mi red WIFI  e iniciamos el servidor.

 WiFiMulti.addAP(ssid, password);
 while(WiFiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
   
  }

  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (mdns.begin("espWebSock", WiFi.localIP())) {
    Serial.println("MDNS responder started");
    mdns.addService("http", "tcp", 80);
    mdns.addService("ws", "tcp", 81);
  }
  else {
    Serial.println("MDNS.begin failed");
  }
  Serial.print("Connect to http://espWebSock.local or http://");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);

  server.begin();

  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
}

Una ves conectado a la red wifi y haya  dado una IP al servidor, empezamos a configurar lo el front end para ser visualizado por el cliente.

<body onload="javascript:start();">
<div id="div1">
<h1 id="text">RC CONTROL</h1>
<input id="textField1" type="text" value="" align="right" size="13"/><br>
<input id="display"    type="text" value="" align="right" size="13"/><br>
</div>

<div id="div2"><b>POWER</b></div>
<div id="div3">
<div id="ledstatus"><b>Estado</b></div>
<button id="ledon"    type="button" onclick="buttonclick(this);">>></button> 
<button id="ledoff"   type="button" onclick="buttonclick(this);">FRENO</button>
<button id="reversa"  type="button" onclick="buttonclick(this);">>></button>
<button id="izquierda"type="button" onclick="buttonclick(this);"><<</button>
<button id="derecha"  type="button" onclick="buttonclick(this);">>></button>
<button id="O"        type="button" onclick="buttonclick(this);">ON</button>
<input id="p"      type="range" min="0" max="255" step="5";>
</div>
</body>
</html>

Como podrán observar el código HTML es muy básico y al cargar la pagina pues se ejecuta el java script que es quien se encarga la lógica de programación. el código CSS pues no viene al tema, al final del proyecto pondré el código completo y podrán descargarlo.

Ahora el código de enlace como lo llamo entre la interacción del cliente con el coche RC

La idea es que al cargar la pagina la funcion start() se ejecuta y crea el socket con el cliente y el coche RC queda a la espera de instrucciones por medio de eventos, en el vídeo explicare mejor esta parte y podrán ver los mensajes cliente/servidor

function start() {
  websock = new WebSocket('ws://' + window.location.hostname + ':81/');
  websock.onopen =   function(evt){console.log('RC ready to drive'); };
  websock.onclose =  function(evt){console.log('RC connection close'); };
  websock.onerror =  function(evt){console.log(evt); };
  websock.onmessage =function(evt){console.log(evt);
    
  
    var e = document.getElementById('ledstatus');
    output = document.getElementById("display");
    output_text = document.getElementById("textField1");
     
       
      if (evt.data === 'ledon') {
      e.style.color = 'red';
      output_text.style.color ='red';
      var state= "Acelerando.."
      output_text.value=state;
             
    }
    else if (evt.data === 'ledoff') {
      e.style.color = 'black';
      //canvas.fillText(state,10,50);
      output_text.style.color ='black';
      var state= "Freno"
      output_text.value=state;
    }
      else if (evt.data === 'reversa') {
      e.style.color = 'black';
      output_text.style.color ='black';
      var state= "Reversa"
      output_text.value=state;
      }
      else if (evt.data === 'izquierda') {
      e.style.color = 'black';
      output_text.style.color ='black';
      var state= "Izquierda"
      output_text.value=state;        
    }
    else if (evt.data === 'derecha') {
      e.style.color = 'black';
      output_text.style.color ='black';
      var state= "Derecha"
      output_text.value=state;        
    }
    else if (evt.data > "100") {
      e.style.color = 'black';
      output.style.color ='black';
      var state= "Velocidad ";
      output.value=(state + evt.data);        
    }
    else {
      console.log('unknown event');
      document.getElementById("text").value = "";
    }
   
  };
}
function buttonclick(e) {
  websock.send(e.id);
 }

Una ves podemos interpretar las instrucciones del cliente pues hacemos andar el coche RC.

Esta parte es muy arduino.

Como había comentado antes el coche queda a la espera de instrucciones por medio de eventos pues el código para interactuar con el coche esta aquí.

Lo que inicia el evento es un mensaje tipo texto, que es el que indica la instrucción “Izquierda” pues el pone a 0 el pin D6 y a HIGH el pin 7 lo que hace que el motor de dirección gire a la izquierda, y así con las demás instrucciones.

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
  
  Serial.printf("webSocketEvent(%d, %d, ...)\r\n", num, type);
  switch(type) {
    case WStype_DISCONNECTED:
      Serial.printf("[%u] Disconnected!\r\n", num);
      break;
    case WStype_CONNECTED:
      {
        IPAddress ip = webSocket.remoteIP(num);
        Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\r\n", num, ip[0], ip[1], ip[2], ip[3], payload);
      
      } 
      break;
    case WStype_TEXT:
    {
      Serial.printf("[%u] get Text: %s\r\n", num, payload);

      String text = String((char *) &payload[0]);
      if(text=="ledon"){
        analogWrite(AcelMotor_pin, acel);  //Pin 5
        acel=acel+10;
        Serial.print("Velocidad ");
        Serial.println(acel);
        analogWrite (Adelante_pin, 1023);   // Pin D6
        analogWrite (Atras_pin,0);          //Pin D7
        String temp =String(acel); // convierte to string
        webSocket.sendTXT(num,temp);
                      
            }
      if(text=="ledoff"){
        Serial.println("break");  
        analogWrite (Adelante_pin, 0);     // Pin D6
        analogWrite (Atras_pin,0);         //Pin D7
            //webSocket.sendTXT(num, "break", 5);
           // analogWrite(LEDPIN, 0);
            acel=500;
            }
       if(text=="reversa"){
        Serial.println("reversa");
        analogWrite(AcelMotor_pin, acel);
        acel=acel+10;
        Serial.println(acel);
        analogWrite (Adelante_pin,0);     // Pin D6
        analogWrite (Atras_pin,1023);     //Pin D7
        webSocket.sendTXT(num, "reversa", length);
            }  
       if(text=="izquierda"){
        flag = true;
        analogWrite(Izquierda_pin, 0); //Pin 2
        analogWrite(Derecha_pin, 1023);      //Pin 1
        Serial.println("izquierda");
           webSocket.sendTXT(num, "girar a la izquierda", 20);
            } 
       if(text=="derecha"){
        flag = true;
        analogWrite(Izquierda_pin, 1023);    //Pin 2
        analogWrite(Derecha_pin, 0);   //Pin 1
        Serial.println("izquierda");
        
          webSocket.sendTXT(num, "girar a la derecha", 18);
            }                         
    

Conclusiones

Estoy muy satisfecho con los resultados la verdad que aprendí mucho, este proyecto es fácil de hacer y económico en comparación con lo que se puede aprender ya que toca electrónica, microprocesadores, html, css, javascript etc….

El problema que tuve que la dirección es que estoy trabajando con un motor dc con escobillas por lo que al inyectar alimentación este gira bruscamente hacia un lado impidiendo una conducción fina, como mejora sustituiré el motor de dirección por un servo motor que es mas adecuado para la dirección en un coche RC

El código no esta depurado por lo que tiene algunas librerías de mas y algunas variable tienen nombre sin sentido, cuando finalice el proyecto del todo ya les dejare un código mas limpio.

Cualquier duda o comentario estoy a su orden.

 

Deja un comentario