Taula de continguts:

DuvelBot: robot de servei de cervesa ESP32-CAM: 4 passos (amb imatges)
DuvelBot: robot de servei de cervesa ESP32-CAM: 4 passos (amb imatges)

Vídeo: DuvelBot: robot de servei de cervesa ESP32-CAM: 4 passos (amb imatges)

Vídeo: DuvelBot: robot de servei de cervesa ESP32-CAM: 4 passos (amb imatges)
Vídeo: Jean-Michel Jarre - Fourth Rendez-Vous 2024, Desembre
Anonim
DuvelBot: robot de servei de cervesa ESP32-CAM
DuvelBot: robot de servei de cervesa ESP32-CAM

Després d’un dur dia de treball, res s’acosta a prendre la vostra cervesa preferida al sofà. En el meu cas, aquesta és la cervesa rossa belga "Duvel". No obstant això, després de tot, però ens ensorrem, ens enfrontem a un problema molt greu: la nevera que conté el meu Duvel està a uns 20 peus insalvables del dit sofà.

Tot i que algunes lleus coaccions del meu costat podrien moure un escombriaire de frigorífics adolescents ocasionals per abocar el permís de Duvel de la meva setmana, la tasca de lliurar-la al seu progenitor gairebé esgotat és, òbviament, un pas massa lluny.

És hora d’esclatar el soldador i el teclat …

DuvelBot és una càmera web de conducció basada en AI-Thinker ESP32-CAM, que podeu controlar des del vostre telèfon intel·ligent, navegador o tauleta.

És fàcil adaptar o ampliar aquesta plataforma a usos menys alcohòlics (penseu en SpouseSpy, NeighbourWatch, KittyCam …).

Vaig construir aquest robot principalment per aprendre una mica sobre tota la programació web i coses de l’IoT, de les quals no sabia res. Així doncs, al final d’aquest instructiu hi ha una explicació detallada de com funciona.

Moltes parts d’aquest instructiu es basen en les excel·lents explicacions que trobareu als tutorials de Random Nerd, així que visiteu-los.

Subministraments

Què necessites:

La llista de peces no està tallada a la pedra i es poden obtenir moltes parts en un munt de versions diferents i des de molts llocs diferents. Vaig procurar-me la majoria amb Ali-Express. Com deia Machete: improvisa.

Maquinari:

  • Mòdul AI Thinker ESP32-CAM. Probablement podria funcionar amb altres mòduls ESP32-CAM, però això és el que he utilitzat
  • Taula de controladors de motor L298N,
  • Una plataforma de robòtica de 4 rodes barata,
  • Una carcassa amb una gran superfície plana com l’Hammond Electronics 1599KGY,
  • Convertidor USB-a-3.3V-TTL per a la programació.
  • Per a la il·luminació: 3 LEDs blancs, BC327 o un altre transistor d’ús general NPN (Ic = 500mA), resistència 4k7k, 3 resistències de 82 Ohm, placa de perfils, cables (vegeu l’esquema i les imatges).
  • Un commutador d'activació / desactivació i un polsador normalment obert per programar.

Opcional:

  • Una càmera d'ull de peix amb una flexió més llarga que la càmera OV2460 estàndard que es proporciona amb el mòdul ESP32-CAM,
  • Antena WiFi amb cable llargament adequat i connector coaxial ultra miniatura, com aquest. L'ESP32-CAM té una antena a bord i la carcassa és de plàstic, de manera que no cal una antena, però em va semblar genial, així que …
  • Paper adhesiu imprimible d'injecció de tinta per al disseny de la coberta superior.

Les eines habituals de ferreteria: soldador, trepants, tornavisos, alicates …

Pas 1: construir la plataforma de robots

Construint la plataforma de robots
Construint la plataforma de robots
Construint la plataforma de robots
Construint la plataforma de robots
Construint la plataforma de robots
Construint la plataforma de robots

L'esquema:

L’esquema no té res d’especial. La càmera ESP32 controla els motors mitjançant la placa de control del motor L298N, que té dos canals. Els motors del costat esquerre i dret es col·loquen en paral·lel i cada costat ocupa un canal. Quatre condensadors ceràmics petits de 10..100nF a prop dels passadors del motor són sempre aconsellables per contrarestar les interferències de RF. A més, un gran tap electrolític (2200 … 4700uF) a l’alimentació de la placa del motor tal com es mostra a l’esquema, tot i que no és estrictament necessari, pot limitar una mica l’ondulació de la tensió d’alimentació (si voleu veure una pel·lícula de terror, proveu Vbat amb un oscil·loscopi mentre els motors estan actius).

Tingueu en compte que els dos canals del motor ENABLE pins estan accionats pel mateix pin d'amplada d'amplada d'impuls (PWM) de l'ESP32 (IO12). Això es deu al fet que el mòdul ESP32-CAM no té una gran quantitat de GPIO (l’esquema del mòdul s’inclou com a referència). Els LED del robot són impulsats per IO4, que també acciona el LED del flaix incorporat, de manera que traieu Q1 per evitar que el LED del flaix s’encengui en un allotjament tancat.

El botó de programació, l’interruptor d’encès / apagat, el connector de càrrega i el connector de programació són accessibles a sota del robot. Hauria pogut fer una feina molt millor pel connector de programació (jack de 3,5 mm?), Però la cervesa no podia esperar més. També seria bo instal·lar actualitzacions per transmissió (OTA).

Per posar el robot en mode de programació, premeu el botó de programació (això fa baixar IO0) i, a continuació, engegueu-lo.

Important: per carregar les bateries NiMH del robot, utilitzeu un subministrament de laboratori (descarregat) a uns 14 V i un corrent limitat a 250 mA. El voltatge s’adaptarà al voltatge de les bateries. Desconnecteu si el robot se sent calent o el voltatge de la bateria arriba als 12,5V. Una millora òbvia aquí seria integrar un carregador de bateria adequat, però això està fora de l’abast d’aquest instructable.

El maquinari:

Consulteu també les notes de les imatges. La carcassa es munta a la base del robot mitjançant 4 perns M4 i femelles autoblocants. Tingueu en compte els tubs de goma utilitzats com a separadors de distància. Amb sort, això també dóna alguna suspensió al Duvel, en cas que el viatge resulti accidentat. El mòdul ESP32-CAM i la placa del motor L298N es munten a la carcassa amb peus enganxosos de plàstic (no estic segur del nom correcte en anglès), per evitar haver de perforar forats addicionals. A més, l'ESP32 està muntat en el seu propi perfboard i capçaleres endollables. Això facilita l'intercanvi de l'ESP32.

No ho oblideu: si aneu amb una antena WiFi externa en lloc de la incorporada, soldeu també el pont de selecció d'antena a la part inferior de la placa ESP32-CAM.

Imprimiu el logotip superior del fitxer DuvelBot.svg en paper adhesiu d'injecció de tinta (o dissenyeu-ne el vostre) i ja podeu llest.

Pas 2: programa el robot

Programa el robot
Programa el robot

Es recomana programar el robot abans de tancar-lo, per assegurar-se que tot funcioni i que no aparegui fum màgic.

Necessiteu les següents eines de programari:

  • L’IDE Arduino,
  • Les biblioteques ESP32, SPIFFS (sistema de fitxers flash perifèrics en sèrie), biblioteca ESPAsync Webserver.

Aquest últim es pot instal·lar seguint aquest tutorial aleatori fins a incloure la secció "organització dels vostres fitxers". Realment no ho podria explicar millor.

El codi:

El meu codi es pot trobar a:

  • Un esbós Arduino DuvelBot.ino,
  • Una subcarpeta de dades que conté els fitxers que es carregaran al flaix ESP mitjançant SPIFFS. Aquesta carpeta conté la pàgina web que servirà l'ESP (index.html), una imatge de logotip que forma part de la pàgina web (duvel.png) i un full d'estil en cascada o un fitxer CSS (style.css).

Per programar el robot:

  • Connecteu el convertidor USB-TTL tal com es mostra a l’esquema,
  • Fitxer -> Obrir -> anar a la carpeta on es troba DuvelBot.ino.
  • Canvieu les credencials de xarxa a l'esbós:

const char * ssid = "yourNetworkSSIDHere"; const char * password = "yourPasswordHere";

  • Eines -> Tauler -> "AI-Thinker ESP-32 CAM" i seleccioneu el port sèrie adequat per al vostre ordinador (Eines -> Port -> alguna cosa com / dev / ttyUSB0 o COM4),
  • Obriu el monitor sèrie a l’IDE Arduino, mentre premeu el botó PROG (que fa baixar IO0), enceneu el robot,
  • Comproveu al monitor sèrie que l’ESP32 estigui a punt per descarregar,
  • Tanqueu el monitor sèrie (en cas contrari, la càrrega SPIFFS falla),
  • Eines -> "Pujada de dades d'esbossos ESP32" i espereu que acabi,
  • Apagueu i torneu a engegar el botó PROG per tornar al mode de programació,
  • Premeu la fletxa "Puja" per programar l'esbós i espereu que acabi,
  • Obriu el monitor sèrie i reinicieu l’ESP32 apagant / encenent,
  • Un cop arrencat, anoteu l'adreça IP (com ara 192.168.0.121) i desconnecteu el robot del convertidor USB-TTL,
  • Obriu un navegador en aquesta adreça IP. Hauríeu de veure la interfície com a la imatge.
  • Opcional: configureu l'adreça mac de l'ESP32 a una adreça IP fixa al vostre encaminador (depèn de com es faci).

Això és! Seguiu llegint si voleu saber com funciona …

Pas 3: Com funciona

Ara arribem a la part interessant: com funciona tot plegat?

Intentaré explicar-ho pas a pas … però tingueu present que Kajnjaps no és un especialista en programació web. De fet, aprendre una mica de programació web era tota la premissa de construir DuvelBot. Si comet errors evidents, deixeu un comentari.

D'acord, després d'engegar ESP32, com és habitual en la configuració, inicialitza els GPIO, els associa amb temporitzadors PWM per al control del motor i del LED. Vegeu aquí per obtenir més informació sobre el control del motor, és bastant estàndard.

A continuació, la càmera està configurada. Vaig mantenir deliberadament la resolució força baixa (VGA o 640x480) per evitar una resposta lenta. Tingueu en compte que la placa AI-Thinker ESP32-CAM té un xip de memòria RAM (PSRAM) que utilitza per emmagatzemar fotogrames de càmera de resolució més gran:

if (psramFound ()) {Serial.println ("PSRAM trobat."); config.frame_size = FRAMESIZE_VGA; config.jpg_quality = 12; config.fb_count = 2; // nombre de framebuffers veure: https://github.com/espressif/esp32-camera} else {Serial.println ("no s'ha trobat cap PSRAM"); config.frame_size = FRAMESIZE_QVGA; config.jpg_quality = 12; config.fb_count = 1; }

A continuació, s'inicialitza el sistema de fitxers flash perifèrics en sèrie (SPIFFS):

// inicialitzeu SPIFFS if (! SPIFFS.begin (true)) {Serial.println ("S'ha produït un error en muntar SPIFFS!"); tornar; }

SPIFFS actua com un petit sistema de fitxers a l’ESP32. Aquí s'utilitza per emmagatzemar tres fitxers: la pàgina web index.html, un fitxer en forma de fitxer en forma de cascada style.css i el logotip de la imatge-p.webp

A continuació, l'ESP32 es connecta al vostre encaminador (no oblideu establir les vostres credencials abans de penjar-les):

// canviar les credencials del vostre router hereconst char * ssid = "yourNetworkSSIDHere"; const char * password = "yourPasswordHere"; … // connectar-se a WiFi Serial.print ("Connexió a WiFi"); WiFi.begin (ssid, contrasenya); while (WiFi.status ()! = WL_CONNECTED) {Serial.print ('.'); retard (500); } // ara està connectat al router: ESP32 ara té adreça IP

Per fer alguna cosa útil, iniciem un servidor web asíncron:

// creeu un objecte AsyncWebServer al port 80AsyncWebServer server (80); … server.begin (); // començar a escoltar connexions

Ara, si escriviu l'adreça IP que l'encaminador va assignar a l'ESP32 a la barra d'adreces del navegador, l'ESP32 rebrà una sol·licitud. Això significa que ha de respondre al client (a vosaltres o al vostre navegador) servint-li alguna cosa, per exemple, una pàgina web.

L'ESP32 sap respondre, ja que en la configuració les respostes a totes les sol·licituds permeses possibles s'han registrat mitjançant server.on (). Per exemple, la pàgina web principal o l'índex (/) es gestiona així:

server.on ("/", HTTP_GET, (petició AsyncWebServerRequest *) {Serial.println ("/ petició rebuda!"); processador);});

Per tant, si el client es connecta, l’ESP32 respon enviant el fitxer index.html des del sistema de fitxers SPIFFS. El processador de paràmetres és el nom d'una funció que preprocessa l'html i substitueix qualsevol etiqueta especial:

// Substitueix els espais reservats a l'html com% DATA% // per les variables que voleu mostrar //

Dades:% DATA%

Processador de cadenes (const String & var) {if (var == "DATA") {//Serial.println("in processador! "); return String (dutyCycleNow); } return String ();}

Ara, permetem desfer la pàgina web index.html en si. En general, sempre hi ha tres parts:

  1. codi html: quins elements s'han de mostrar (botons / text / control lliscant / imatges, etc.),
  2. codi d'estil, ja sigui en un fitxer.css separat o en una secció …: com haurien de ser els elements,
  3. javascript a … secció: com ha d'actuar la pàgina web.

Un cop index.html es carrega al navegador (que sap que és html a causa de la línia DOCTYPE), entra en aquesta línia:

Es tracta d’una sol·licitud d’un full d’estil CSS. La ubicació d’aquest full es dóna a href = "…". Què fa, doncs, el vostre navegador? Dret, llança una altra sol·licitud al servidor, aquesta vegada per style.css. El servidor capta aquesta sol·licitud perquè estava registrada:

server.on ("/ style.css", HTTP_GET, (sol·licitud AsyncWebServerRequest *) {Serial.println ("s'ha rebut la sol·licitud css"); request-> send (SPIFFS, "/style.css", "text / css ");});

Neat eh? Per cert, podria haver estat href = "/ some / file / on / the / other / side / of / the / moon", per a tot el vostre navegador. Aniria a buscar aquest fitxer amb la mateixa felicitat. No explicaré el full d'estils, ja que només controla les aparences, de manera que aquí no és realment interessant, però si voleu obtenir més informació, consulteu aquest tutorial.

Com apareix el logotip de DuvelBot? A index.html tenim:

a la qual l'ESP32 respon amb:

server.on ("/ duvel", HTTP_GET, (sol·licitud AsyncWebServerRequest *) {Serial.println ("s'ha rebut la sol·licitud de logotip de duvel!"); ");});

..un altre fitxer SPIFFS, aquesta vegada una imatge completa, tal com indica "image / png" a la resposta.

Ara arribem a la part realment interessant: el codi dels botons. Anem a centrar-nos en el botó ENDAVANT:

ENDAVANT

El nom class = "…" només és un nom per enllaçar-lo al full d'estil per personalitzar la mida, el color, etc. Les parts importants són onmousedown = "toggleCheckbox ('forward')" i onmouseup = "toggleCheckbox ('stop') ". Aquests constitueixen les accions del botó (el mateix per a ontouchstart / ontouchend, però per a això són pantalles tàctils / telèfons). Aquí, l'acció del botó crida a una funció toggleCheckbox (x) a la secció javascript:

funció toggleCheckbox (x) {var xhr = new XMLHttpRequest (); xhr.open ("GET", "/" + x, true); xhr.send (); // també podríem fer alguna cosa amb la resposta quan estiguem preparats, però no ho fem}

Per tant, en prémer el botó d’enviament, es produeix immediatament una trucada a toggleCheckbox ('endavant'). A continuació, aquesta funció llança un XMLHttpRequest "GET", de la ubicació "/ forward", que funciona com si haguéssiu escrit 192.168.0.121/forward a la barra d'adreces del navegador. Un cop aquesta sol·licitud arriba a l'ESP32, la gestionen:

server.on ("/ reenviament", HTTP_GET, (sol·licitud AsyncWebServerRequest *) {Serial.println ("rebut / reenviament"); actionNow = FORWARD; request-> send (200, "text / plain", "OK forward. ");});

Ara l'ESP32 simplement respon amb un text "OK endavant". Tingueu en compte que toggleCheckBox () no fa res amb (o espereu) aquesta resposta, però, tal com es pot veure més endavant al codi de la càmera.

Durant aquesta resposta, el programa només estableix una variable actionNow = FORWARD, com a resposta a prémer el botó. Ara, al mainloop del programa, aquesta variable es controla amb l'objectiu de pujar / baixar el PWM dels motors. La lògica és: mentre tinguem una acció que no sigui STOP, pugem els motors en aquesta direcció fins que s’assoleixi un nombre determinat (dutyCycleMax). A continuació, mantingueu aquesta velocitat sempre que l’acció ActionNow no hagi canviat:

bucle buit () {currentMillis = millis (); if (currentMillis - previousMillis> = dutyCycleStepDelay) {// desa la darrera vegada que vau executar el bucle previousMillis = currentMillis; // mainloop s’encarrega de pujar / baixar els motors si (actionNow! = actionAction anterior) {// ramp down, then stop, then change action and ramp up dutyCycleNow = dutyCycleNow-dutyCycleStep; if (dutyCycleNow <= 0) {// si després de baixar DC és 0, estableix la nova direcció, comença a min dutycycle setDir (actionNow); actionAction = actionNow; dutyCycleNow = dutyCycleMin; }} else // actionNow == previousAction ramp up up, exceptuant quan la direcció és STOP {if (actionNow! = STOP) {dutyCycleNow = dutyCycleNow + dutyCycleStep; if (dutyCycleNow> dutyCycleMax) dutyCycleNow = dutyCycleMax; } else dutyCycleNow = 0; } ledcWrite (pwmChannel, dutyCycleNow); // ajustar el motor de duticicle}}

Això augmenta lentament la velocitat dels motors, en lloc de llançar-se a tota velocitat i vessar el preuat Duvel. Una millora òbvia seria moure aquest codi a una rutina d’interrupció del temporitzador, però funciona tal qual.

Ara, si deixem anar el botó d’enviament, el navegador crida a toggleCheckbox ("aturar"), donant lloc a una sol·licitud de GET / stop. L'ESP32 estableix actionNow a STOP (i respon amb "OK stop"), que dóna pas al mainloop per fer girar els motors.

Què passa amb els LED? El mateix mecanisme, però ara tenim un control lliscant:

Al javascript, es controla la configuració del control lliscant, de manera que en cada canvi es produeix una trucada per obtenir "/ LED / xxx", on xxx és el valor de brillantor en què s'han de definir els LED:

var slide = document.getElementById ('slide'), sliderDiv = document.getElementById ("sliderAmount"); slide.onchange = function () {var xhr = new XMLHttpRequest (); xhr.open ("GET", "/ LED /" + this.value, true); xhr.send (); sliderDiv.innerHTML = aquest valor; }

Tingueu en compte que hem utilitzat document.getElementByID ('diapositiva') per obtenir el propi objecte lliscant, amb el qual s'ha declarat i que el valor s'expedeix a un element de text amb cada canvi.

El controlador de l’esbós captura totes les sol·licituds de brillantor mitjançant l’ús de "/ LED / *" al registre del controlador. A continuació, l'última part (un número) es divideix i es converteix en un int:

server.on ("/ LED / *", HTTP_GET, (petició AsyncWebServerRequest *) {Serial.println ("sol·licitud led rebuda!"); setLedBrightness ((request-> url ()). subcadena (5).toInt ()); request-> send (200, "text / plain", "OK Leds.");});

De la mateixa manera que es va descriure anteriorment, els botons radioactius controlen les variables que configuren els valors predeterminats de PWM, de manera que DuvelBot pugui anar lentament amb la cervesa, amb compte de no vessar aquell or líquid i tornar ràpidament a la cuina per obtenir una mica més.

… Llavors, com s'actualitza la imatge de la càmera sense haver d'actualitzar la pàgina? Per a això fem servir una tècnica anomenada AJAX (JavaScript i XML asíncrons). El problema és que normalment una connexió client-servidor segueix un procediment fix: client (navegador) fa una sol·licitud, servidor (ESP32) respon, cas tancat. Fet. Ja no passa res. Si d’alguna manera poguéssim enganyar el navegador per demanar actualitzacions periòdicament a l’ESP32 … i això és exactament el que farem amb aquest fragment de javascript:

setInterval (function () {var xhttp = new XMLHttpRequest (); xhttp.open ("GET", "/ CAMERA", true); xhttp.responseType = "blob"; xhttp.timeout = 500; xhttp.ontimeout = function () {}; xhttp.onload = function (e) {if (this.readyState == 4 && this.status == 200) {// veure: https://stackoverflow.com/questions/7650587/using… // https://www.html5rocks.com/en/tutorials/file/xhr2/ var urlCreator = window. URL || window.webkitURL; var imageUrl = urlCreator.createObjectURL (this.response); // creeu un objecte a partir del blob document.querySelector ("# camimage"). src = imageUrl; urlCreator.revokeObjectURL (imageurl)}}; xhttp.send ();}, 250);

setInterval pren com a paràmetre una funció i l'executa cada cert temps (aquí una vegada per 250 ms resultant en 4 fotogrames / segon). La funció que s'executa fa una sol·licitud d'un "blob" binari a l'adreça / CÀMERA. Això s’encarrega a l’ESP32-CAM de l’esbós com (de Randomnerdtutorials):

server.on ("/ CAMERA", HTTP_GET, (petició AsyncWebServerRequest *) {Serial.println ("s'ha rebut la sol·licitud de càmera!"); camera_fb_t * fb = NULL; // esp_err_t res = ESP_OK; size_t _jpg_buf_len = 0; uint8_t * _jpg_buf = NULL; // captura un marc fb = esp_camera_fb_get (); if (! fb) {Serial.println ("No s'ha pogut adquirir el buffer de fotogrames"); retorna;} if (fb-> format! = PIXFORMAT_JPEG) / / ja en aquest format des de config {bool jpeg_converted = frame-j.webp

Les parts més importants són aconseguir que el marc fb = esp_camera_fb_get () el converteixi en-j.webp

A continuació, la funció javascript espera que arribi aquesta imatge. Aleshores, només cal una mica de feina per convertir el "blob" rebut en un URL que es pot utilitzar com a font per actualitzar la imatge a la pàgina html.

uf, ja hem acabat!

Pas 4: idees i restes

Idees i restes
Idees i restes

L’objectiu d’aquest projecte per a mi era aprendre la programació web suficient per connectar el maquinari a la web. Són possibles diverses extensions d’aquest projecte. Aquí teniu algunes idees:

  • Implementeu la transmissió de la càmera "real" tal com s'explica aquí i aquí i moveu-la a un segon servidor tal com s'explica aquí al mateix ESP32, però a l'altre nucli de la CPU, a continuació, importeu la càmera de transmissió a l'html servit pel primer servidor mitjançant un … Això hauria de provocar actualitzacions de la càmera més ràpides.
  • Utilitzeu el mode de punt d'accés (AP) perquè el robot sigui més independent, tal com s'explica aquí.
  • Amplieu amb la mesura del voltatge de la bateria, les capacitats de son profund, etc. Això és una mica difícil en aquest moment perquè l'AI-Thinker ESP32-CAM no té molts GPIO; necessita una expansió via uart i, per exemple, un arduino esclau.
  • Convertiu-lo en un robot que busca gat que expulsa de tant en tant tractes de gats en prémer la pota d'un botó gran, emetre un munt de bones fotos del gat durant el dia …

Si us plau, comenteu si us han agradat o teniu preguntes i gràcies per llegir-les.

Recomanat: