En este proyecto vamos a ver cómo
fabricar un vehículo con un protoboard, algunas piezas impresas, dos
moto-reductores para Arduino y unas pocas piezas más. El vehículo está
conectado a un NodeMCU mediante un driver L293D, el ESP8266 está funcionado en
modo SoftAP y tiene alojado un webserver con websokets, lo que permite
controlar el vehículo, sin latencia, desde una aplicación web basada en
JavaScript.
Lista de Materiales:
1) NodeMCU (ESP8266)
1) L293D
1) Cargador USB portátil 5V 5600mah
1) Cable USB
1) Cable USB
2) Motor DC 3v A 6v caja reductora rueda goma para Arduino
2) Rodamientos 624zz
2) Tornilos de 5/32"W x 5/8 (ó M4x16)
2) Tuercas de 5/32"W (ó M4)
2) Arandelas grower de 5/32"
2) Tornilos de 5/32"W x 5/8 (ó M4x16)
2) Tuercas de 5/32"W (ó M4)
2) Arandelas grower de 5/32"
1) Protoboard 830 puntos
#include <ESP8266WiFi.h> #include <WebSocketsServer.h> #include <ESP8266WebServer.h> #define PWM_IZQ 05 // D1 #define PWM_DER 04 // D2 #define IZQ_AVZ 14 // D5 #define IZQ_RET 12 // D6 #define DER_AVZ 13 // D7 #define DER_RET 02 // D4 const char* ssid = "Vehiculo"; const char* password = "asdfghjk"; String pagina ="<html>" "<head>" "<style type='text/css'>" "* { margin: 0px; padding: 20px; }" "#avz, #ret { width: 100%; height: 33%; }" "#izq, #der { width: 49.7%; height: 33% }" "input[type=range] { height: 26px; -webkit-appearance: none; margin: 10px 0; width: 120px; }" "input[type=range]:focus { outline: none; }" "input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 50px; cursor: pointer; animate: 0.2s; box-shadow: 1px 1px 1px #50555C; " " background: #50555C; border-radius: 25px; border: 0px solid #000000; }" "input[type=range]::-webkit-slider-thumb { box-shadow: 0px 0px 0px #000000; border: 0px solid #000000; height: 80px; width: 80px; border-radius: 25px;" " background: #007FFF; cursor: pointer; -webkit-appearance: none; margin-top: -15px; }" "input[type=range]:focus::-webkit-slider-runnable-track { background: #50555C; }" "input[type=range]:focus::-ms-fill-lower { background: #50555C; }" "input[type=range]:focus::-ms-fill-upper { background: #50555C; }" "</style>" "<script>" "var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']);" "connection.onopen = function () { connection.send('Connect ' + new Date()); };" "connection.onerror = function (error) { console.log('WebSocket Error ', error);};" "connection.onmessage = function (e) { console.log('Server: ', e.data);};" "function sendAvz() {" "var avz = parseInt(document.getElementById('avz').value);" "var dir = '#';" "if(avz < 16) { dir = dir + '+' + avz.toString(16) + '+f'; }" "if(avz >= 16) { avz = 31 - avz; dir = dir + '+f+' + avz.toString(16); }" "console.log(dir);" "connection.send(dir);" "}" "function sendIzq() {" "var izq = parseInt(document.getElementById('izq').value);" "izq = 15 - izq;" "var dir = '#';" "dir = dir + '-' + izq.toString(16) + '+' + izq.toString(16);" "console.log(dir);" "connection.send(dir);" "}" "function sendDer() {" "var der = parseInt(document.getElementById('der').value);" "var dir = '#';" "dir = dir + '+' + der.toString(16) + '-' + der.toString(16);" "console.log(dir);" "connection.send(dir);" "}" "function sendRet() {" "var ret = parseInt(document.getElementById('ret').value);" "var dir = '#';" "if(ret < 16) { dir = dir + '-' + ret.toString(16) + '-f'; }" "if(ret >= 16) { ret = 31 - ret; dir = dir + '-f-' + ret.toString(16); }" "console.log(dir);" "connection.send(dir);" "}" "function SendParar() { console.log('#+0+0'); connection.send('#+0+0'); }" "</script>" "</head>" "<body>" "<input id='avz' type='range' min='0' max='31' step='1' value='16' oninput='sendAvz();' onmouseup='SendParar();' ontouchend='SendParar();'/>" "<input id='izq' type='range' min='0' max='15' step='1' value='16' oninput='sendIzq();' onmouseup='SendParar();' ontouchend='SendParar();'/>" "<input id='der' type='range' min='0' max='15' step='1' value='0' oninput='sendDer();' onmouseup='SendParar();' ontouchend='SendParar();'/>" "<input id='ret' type='range' min='0' max='31' step='1' value='16' oninput='sendRet();' onmouseup='SendParar();' ontouchend='SendParar();'/>" "</body>" "</html>"; ESP8266WebServer server = ESP8266WebServer(80); WebSocketsServer webSocket = WebSocketsServer(81); void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { switch(type) { case WStype_DISCONNECTED: Serial.printf("[%u] Disconnected!\n", num); analogWrite(PWM_IZQ, 0); analogWrite(PWM_DER, 0); break; case WStype_CONNECTED: { IPAddress ip = webSocket.remoteIP(num); Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); // send message to client webSocket.sendTXT(num, "Connected"); } break; case WStype_TEXT: Serial.printf("[%u] get Text: %s\n", num, payload); if(payload[0] == '#') { if(payload[1] == '+') { digitalWrite(IZQ_AVZ, 0); digitalWrite(IZQ_RET, 1); } if(payload[1] == '-') { digitalWrite(IZQ_AVZ, 1); digitalWrite(IZQ_RET, 0); } if(payload[3] == '+') { digitalWrite(DER_AVZ, 0); digitalWrite(DER_RET, 1); } if(payload[3] == '-') { digitalWrite(DER_AVZ, 1); digitalWrite(DER_RET, 0); } uint8_t izq = (uint8_t) strtol((const char *) &payload[2], NULL, 16); uint8_t der = (uint8_t) strtol((const char *) &payload[4], NULL, 16); analogWrite(PWM_IZQ, izq); analogWrite(PWM_DER, der); } break; } } void setup() { Serial.begin(115200); Serial.println(); WiFi.softAP(ssid, password); IPAddress myIP = WiFi.softAPIP(); Serial.print("IP del access point: "); Serial.println(myIP); Serial.println("WebServer iniciado..."); pinMode(PWM_IZQ, OUTPUT); pinMode(PWM_DER, OUTPUT); pinMode(IZQ_AVZ, OUTPUT); pinMode(IZQ_RET, OUTPUT); pinMode(DER_AVZ, OUTPUT); pinMode(DER_RET, OUTPUT); // start webSocket server webSocket.begin(); webSocket.onEvent(webSocketEvent); // handle index server.on("/", []() { server.send(200, "text/html", pagina); }); server.begin(); digitalWrite(PWM_IZQ, 0); digitalWrite(PWM_DER, 0); digitalWrite(IZQ_AVZ, 1); digitalWrite(IZQ_RET, 1); digitalWrite(DER_AVZ, 1); digitalWrite(DER_RET, 1); analogWriteRange(15); } void loop() { webSocket.loop(); server.handleClient(); }