Innehållsförteckning:

DuvelBot - ESP32 -CAM ölserveringsrobot: 4 steg (med bilder)
DuvelBot - ESP32 -CAM ölserveringsrobot: 4 steg (med bilder)

Video: DuvelBot - ESP32 -CAM ölserveringsrobot: 4 steg (med bilder)

Video: DuvelBot - ESP32 -CAM ölserveringsrobot: 4 steg (med bilder)
Video: Голубая стрела (1958) фильм 2024, Juni
Anonim
DuvelBot - ESP32 -CAM ölserveringsrobot
DuvelBot - ESP32 -CAM ölserveringsrobot

Efter en hård dags arbete kommer ingenting i närheten av att smutta på din favoritöl i soffan. I mitt fall är det den belgiska blonda ölen "Duvel". Men trots allt, kollapsar vi med ett allvarligt problem: kylskåpet som innehåller min Duvel är en oöverbryggbar 20 fot bort från soffan.

Medan lite lätt tvång från min sida kan flytta en och annan tonårig kylskåp för att hälla ut min veckos ersättning för Duvel, är uppgiften att faktiskt leverera den till sin nästan utmattade förfader uppenbarligen ett steg för långt.

Dags att bryta ut lödkolven och tangentbordet …

DuvelBot är en utan krusiduller AI-Thinker ESP32-CAM-baserad körwebbkamera som du kan styra från din smartphone, webbläsare eller surfplatta.

Det är lätt att anpassa eller utöka denna plattform till mindre alkoholhaltiga användningsområden (tänk SpouseSpy, NeighbourWatch, KittyCam …).

Jag byggde denna robot främst för att lära mig lite om hela webbprogrammeringen och IoT -saker, som jag inte visste något om. Så i slutet av denna Instructable är en utförlig förklaring av hur det fungerar.

Många delar av denna instruktionsbok är baserade på de utmärkta förklaringarna som finns på Random Nerd Tutorials, så besök dem gärna!

Tillbehör

Vad du behöver:

Dellistan är inte huggen i sten och många delar kan erhållas i massor av olika versioner och från många olika platser. Jag skaffade mest från Ali-Express. Som Machete sa: improvisera.

Hårdvara:

  • AI-tänkare ESP32-CAM-modul. Det kan förmodligen fungera med andra ESP32-CAM-moduler men det är vad jag använde
  • L298N motordrivkort,
  • En billig 4-hjulig robotplattform,
  • Ett hus med en stor plan yta som Hammond Electronics 1599KGY,
  • USB-till-3.3V-TTL-omvandlare för programmering.
  • För belysningen: 3 vita lysdioder, BC327 eller annan generell transistor NPN (Ic = 500mA), 4k7k motstånd, 3 82Ohm motstånd, perfboard, kablar (se schemat och bilder).
  • En på/av-omkopplare och en normalt öppen tryckknapp för programmering.

Frivillig:

  • En fisheye-kamera med längre flex än den vanliga OV2460-kameran som medföljer ESP32-CAM-modulen,
  • WiFi -antenn med lämplig lång kabel och Ultra Miniature Coax Connector, så här. ESP32-CAM har en inbyggd antenn och höljet är av plast, så en antenn behövs inte riktigt, men jag tyckte att det såg coolt ut, så …
  • Utskriftsbart klistermärkepapper för bläckstråleskrivare för designen av topplocket.

De vanliga hårdvaruverktygen: lödkolv, borrar, skruvmejslar, tänger …

Steg 1: Bygga robotplattformen

Bygga robotplattformen
Bygga robotplattformen
Bygga robotplattformen
Bygga robotplattformen
Bygga robotplattformen
Bygga robotplattformen

Schemat:

Schemat är inget speciellt. ESP32-cam styr motorerna via motorstyrkortet L298N, som har två kanaler. Motorer på vänster och höger sida är placerade parallellt och varje sida upptar en kanal. Fyra små 10..100nF keramiska kondensatorer nära motorstiften är som alltid lämpligt för att motverka RF -störningar. Dessutom kan ett stort elektrolytlock (2200… 4700uF) på motorns kretskort, som visas i schemat, även om det inte är absolut nödvändigt, begränsa matningsspänningsribblingen lite (om du vill se en skräckfilm, sonda sedan Vbat med ett oscilloskop medan motorerna är aktiva).

Observera att båda motorkanalernas ENABLE-stift drivs av samma pulsbreddsmodulerade (PWM) stift på ESP32 (IO12). Detta beror på att ESP32-CAM-modulen inte har massor av GPIO (modulens schema ingår som referens). Robotens lysdioder drivs av IO4, som också driver den inbyggda blixtlampan, så ta bort Q1 för att förhindra att blixtlampan lyser i ett slutet hus.

Programmeringsknapp, på/av -omkopplare, laddningskontakt och programmeringskontakt är tillgängliga under roboten. Jag kunde ha gjort ett mycket bättre jobb för programmeringskontakten (3,5 mm -uttag?), Men ölen kunde inte vänta längre. Även över-the-air-uppdateringar (OTA) skulle vara trevligt att installera.

För att sätta roboten i programmeringsläge, tryck på programmeringsknappen (detta drar IO0 lågt) och slå sedan på den.

Viktigt: För att ladda NiMH -batterierna i roboten, använd en laboratoriesats (laddad) till ca 14V och ström begränsad till 250mA. Spänningen anpassas till batteriernas spänning. Koppla bort om roboten känns varm eller batterispänningen når cirka 12,5V. En uppenbar förbättring här skulle vara att integrera en korrekt batteriladdare, men det ligger utanför tillämpningsområdet för denna instruerbara.

Hårdvaran:

Se även anteckningarna på bilderna. Huset är monterat på robotbasen med 4 M4-bultar och självlåsande muttrar. Observera gummislangen som används som distanshållare. Förhoppningsvis ger detta också lite upphängning till Duvel, om resan skulle bli ojämn. ESP32-CAM-modulen och motorkortet L298N monteras i höljet med hjälp av klibbiga fötter av plast (inte säker på rätt namn på engelska), för att förhindra att man behöver borra extra hål. Även ESP32 är monterad på en egen perfboard och pluggbara pinheaders. Detta gör det enkelt att byta ut ESP32.

Glöm inte: om du går med en extern WiFi-antenn istället för den inbyggda, löd också antennvalshopparen på undersidan av ESP32-CAM-kortet.

Skriv ut den översta logotypen i filen DuvelBot.svg på bläckstrålepapper (eller designa ditt eget), och du är redo att gå!

Steg 2: Programmera roboten

Programmera roboten
Programmera roboten

Det är lämpligt att programmera roboten innan du stänger den, för att se till att allt fungerar och att ingen magisk rök dyker upp.

Du behöver följande programverktyg:

  • Arduino IDE,
  • ESP32 -biblioteken, SPIFFS (seriellt perifert flashfilsystem), ESPAsync -webbserverbibliotek.

Den senare kan installeras genom att följa denna randomnerd -handledning till och med avsnittet "organisera dina filer". Jag kunde verkligen inte förklara det bättre.

Koden:

Min kod finns på:

  • En Arduino -skiss DuvelBot.ino,
  • En undermapp som innehåller de filer som ska laddas upp till ESP -blixten med SPIFFS. Den här mappen innehåller webbsidan som ESP kommer att visa (index.html), en logotypbild som ingår i webbsidan (duvel.png) och ett kaskadformat eller CSS -fil (style.css).

För att programmera roboten:

  • Anslut USB-TTL-omvandlaren enligt diagrammet,
  • Arkiv -> Öppna -> gå till mapp där DuvelBot.ino är.
  • Ändra dina nätverksuppgifter i skissen:

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

  • Verktyg -> Kort -> "AI -Thinker ESP -32 CAM" och välj lämplig seriell port för din dator (Verktyg -> Port -> något liknande /dev /ttyUSB0 eller COM4),
  • Öppna den seriella bildskärmen i Arduino IDE, medan du trycker på PROG -knappen (som drar IO0 lågt), slå på roboten,
  • Kontrollera på seriell bildskärm att ESP32 är redo för nedladdning,
  • Stäng seriell bildskärm (annars misslyckas överföringen av SPIFFS),
  • Verktyg -> "ESP32 Sketch Data Upload" och vänta tills det är klart,
  • Slå av och på igen genom att hålla PROG -knappen intryckt för att återgå till programmeringsläge,
  • Tryck på "Ladda upp" -pilen för att programmera skissen och vänta tills den är klar,
  • Öppna seriell bildskärm och återställ ESP32 genom att stänga av/på,
  • När den har startat noterar du ip-adressen (ungefär 192.168.0.121) och kopplar bort roboten från USB-TTL-omvandlaren,
  • Öppna en webbläsare på denna ip -adress. Du bör se gränssnittet som på bilden.
  • Valfritt: ställ in mac-adressen för ESP32 till en fast ip-adress i din router (beror på router hur du gör).

Det är allt! Läs om du vill veta hur det fungerar …

Steg 3: Hur det fungerar

Nu kommer vi till den intressanta delen: hur fungerar det hela?

Jag ska försöka förklara det steg för steg … men kom ihåg att Kajnjaps inte är en webbprogrammeringsspecialist. Faktum är att lära sig lite webbprogrammering var hela förutsättningen för att bygga DuvelBot. Om jag gör uppenbara misstag, vänligen lämna en kommentar!

Ok, efter att ESP32 har slagits på, som vanligt vid installationen initierar det GPIO: erna, associerar dem med PWM -timers för motor- och LED -styrning. Se här för mer information om motorstyrning, det är ganska standard.

Då är kameran konfigurerad. Jag höll medvetet upplösningen ganska låg (VGA eller 640x480) för att undvika trög respons. Observera att AI-Thinker ESP32-CAM-kortet har ett seriellt ramchip (PSRAM) som det använder för att lagra kameraramar med större upplösning:

if (psramFound ()) {Serial.println ("PSRAM hittades."); config.frame_size = FRAMESIZE_VGA; config.jpg_quality = 12; config.fb_count = 2; // antal framebuffers se: https://github.com/espressif/esp32-camera} else {Serial.println ("ingen PSRAM hittades."); config.frame_size = FRAMESIZE_QVGA; config.jpg_quality = 12; config.fb_count = 1; }

Sedan initieras det seriella perifera flashfilsystemet (SPIFFS):

// initiera SPIFFS om (! SPIFFS.begin (true)) {Serial.println ("Ett fel har uppstått vid montering av SPIFFS!"); lämna tillbaka; }

SPIFFS fungerar som ett litet filsystem på ESP32. Här används den för att lagra tre filer: själva webbsidan index.html, ett kaskadfilformatark stil.css och en-p.webp

Därefter ansluter ESP32 till din router (glöm inte att ange dina uppgifter innan du laddar upp):

// ändra referenser för din router hereconst char* ssid = "yourNetworkSSIDHere"; const char* password = "yourPasswordHere"; … // ansluta till WiFi Serial.print ("Ansluter till WiFi"); WiFi.begin (ssid, lösenord); medan (WiFi.status ()! = WL_CONNECTED) {Serial.print ('.'); fördröjning (500); } // nu ansluten till routern: ESP32 har nu ip -adress

För att faktiskt göra något användbart startar vi en asynkron webbserver:

// skapa ett AsyncWebServer -objekt på port 80AsyncWebServer -server (80); … server.begin (); // börja lyssna efter anslutningar

Om du skriver in ip -adressen som tilldelades ESP32 av routern i webbläsarens adressfält får ESP32 en begäran. Det betyder att den ska svara klienten (du eller din webbläsare) genom att servera den något, till exempel en webbsida.

ESP32 vet hur man svarar, för vid installationen har svaren på alla möjliga tillåtna förfrågningar registrerats med server.on (). Till exempel hanteras huvudsidan eller indexet (/) så här:

server.on ("/", HTTP_GET, (AsyncWebServerRequest *begäran) {Serial.println ("/begäran mottagen!"); begär-> skicka (SPIFFS, "/index.html", String (), false, processor);});

Så om klienten ansluter svarar ESP32 genom att skicka filen index.html från SPIFFS -filsystemet. Parameterprocessorn är namnet på en funktion som förbehandlar HTML -filen och ersätter eventuella specialtaggar:

// Ersätter platshållare i html som %DATA %// med variablerna du vill visa //

Data: %DATA %

Strängprocessor (const String & var) {if (var == "DATA") {//Serial.println("in processor! "); retursträng (dutyCycleNow); } retursträng ();}

Nu kan vi avlägsna själva index.html -webbsidan. I allmänhet finns det alltid tre delar:

  1. html -kod: vilka element som ska visas (knappar/text/reglage/bilder etc.),
  2. stilkod, antingen i en separat.css -fil eller i ett … avsnitt: hur elementen ska se ut,
  3. javascript a … avsnitt: hur webbsidan ska agera.

När index.html har lästs in i webbläsaren (som vet att det är html på grund av DOCTYPE -raden) körs den in på den här raden:

Det är en begäran om ett CSS -stilark. Platsen för detta blad anges i href = "…". Så vad gör din webbläsare? Precis, det lanserar en annan begäran till servern, den här gången för style.css. Servern fångar upp denna begäran eftersom den registrerades:

server.on ("/style.css", HTTP_GET, (AsyncWebServerRequest *begäran) {Serial.println ("css begäran mottagen"); request-> skicka (SPIFFS, "/style.css", "text/css ");});

Snyggt va? För övrigt kan det ha varit href = "/some/file/on/the/other/side/of/the/moon", för all din webbläsare brydde sig. Det skulle gå att hämta den filen lika gärna. Jag kommer inte att förklara om stilarket eftersom det bara styr utseende så det är inte riktigt intressant här, men om du vill lära dig mer, kolla in den här självstudien.

Hur ser DuvelBot -logotypen ut? I index.html har vi:

som ESP32 svarar med:

server.on ("/duvel", HTTP_GET, (AsyncWebServerRequest *begäran) {Serial.println ("begäran om dubllogotyp mottagen!"); begär-> skicka (SPIFFS, "/duvel.png", "image/png ");});

..en annan SPIFFS -fil, denna gång en komplett bild, som indikeras av "image/png" i svaret.

Nu kommer vi till den riktigt intressanta delen: koden för knapparna. Låt oss fokusera på knappen FRAMÅT:

FRAM

Class = "…" -namnet är bara ett namn för att länka det till formatmallen för att anpassa storlek, färg osv. De viktiga delarna är onmousedown = "toggleCheckbox ('forward')" och onmouseup = "toggleCheckbox ('stop') ". Dessa utgör knapparna (samma för ontouchstart/ontouchend men för det är pekskärmar/telefoner). Här kallar knappåtgärden en funktion toggleCheckbox (x) i javascript -avsnittet:

function toggleCheckbox (x) {var xhr = new XMLHttpRequest (); xhr.open ("GET", "/" + x, true); xhr.send (); // kan göra något med svaret också när vi är redo, men det gör vi inte}

Så genom att trycka på framåtknappen, resulterar det omedelbart i att växlingskryssningsrutan ("framåt") blir uppringd. Denna funktion startar sedan en XMLHttpRequest "GET", av platsen "/forward" som fungerar precis som om du skulle ha skrivit 192.168.0.121/forward i webbläsarens adressfält. När denna begäran kommer till ESP32 hanteras den av:

server.on ("/forward", HTTP_GET, (AsyncWebServerRequest *begäran) {Serial.println ("mottagen/vidarebefordran"); actionNow = FORWARD; request-> send (200, "text/plain", "OK forward. ");});

Nu svarar ESP32 helt enkelt med texten "OK forward". Notera toggleCheckBox () gör inget med (eller vänta på) detta svar, men det kan som visas senare i kamerakoden.

I sig under detta svar ställer programmet bara in en variabel actionNow = FRAMÅT, som svar på att trycka på knappen. Nu i programmets huvudloop övervakas denna variabel med målet att öka/sänka motorns PWM. Logiken är: så länge vi har en åtgärd som inte är STOPP, ska du öka motorerna i den riktningen tills ett visst antal (dutyCycleMax) har uppnåtts. Upprätthåll sedan den hastigheten, så länge actionNow inte har ändrats:

void loop () {currentMillis = millis (); if (currentMillis - previousMillis> = dutyCycleStepDelay) {// spara sista gången du körde loopen previousMillis = currentMillis; // mainloop är ansvarig för att öka/sänka motorerna om (actionNow! = previousAction) {// rampa ner, sedan stoppa, sedan ändra åtgärd och rampa upp dutyCycleNow = dutyCycleNow-dutyCycleStep; om (dutyCycleNow <= 0) {// om dc efter nedrampning är 0, sätt till den nya riktningen, börja med min dutycycle setDir (actionNow); previousAction = actionNow; dutyCycleNow = dutyCycleMin; }} else // actionNow == previousAction ramp up, utom när riktningen är STOPP {if (actionNow! = STOP) {dutyCycleNow = dutyCycleNow+dutyCycleStep; if (dutyCycleNow> dutyCycleMax) dutyCycleNow = dutyCycleMax; } annars dutyCycleNow = 0; } ledcWrite (pwmChannel, dutyCycleNow); // justera motorcykeln}}

Detta ökar långsamt motorernas hastighet, istället för att bara starta i full fart och spilla den dyrbara Duvel. En uppenbar förbättring skulle vara att flytta den här koden till en timeravbrottsrutin, men den fungerar som den är.

Om vi släpper framåtknappen ringer din webbläsare toggleCheckbox ('stopp'), vilket resulterar i en begäran om att få /stoppa. ESP32 ställer in actionNow till STOPP (och svarar med "OK stop."), Som använder huvudslingan för att snurra ner motorerna.

Hur är det med lysdioderna? Samma mekanism, men nu har vi ett reglage:

I javascript övervakas inställningen av reglaget, så att vid varje ändring sker ett samtal för att få "/LED/xxx", där xxx är det ljusstyrka som lysdioderna ska ställas in på:

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 = this.value; }

Observera att vi använde document.getElementByID ('slide') för att hämta själva skjutreglaget, som deklarerades med och att värdet matas ut till ett textelement med vid varje ändring.

Handläggaren i skissen fångar upp alla ljusstyrka med hjälp av "/LED/*" i hanterarregistreringen. Sedan delas den sista delen (ett nummer) av och gjuts till en int:

server.on ("/LED/ *", HTTP_GET, (AsyncWebServerRequest *begäran) {Serial.println ("led-begäran mottagen!"); setLedBrightness ((request-> url ()). delsträng (5).toInt ()); begär-> skicka (200, "text/vanlig", "OK Leds.");});

På samma sätt som beskrivits ovan styr radioknapparna variabler som ställer in PWM -standardvärdena, så att DuvelBot kan köra långsamt till dig med ölet, var noga med att inte spilla det flytande guldet och snabbt tillbaka till köket för att hämta lite mer.

… Så hur uppdateras kamerabilden utan att du behöver uppdatera sidan? För det använder vi en teknik som kallas AJAX (asynkron JavaScript och XML). Problemet är att en klient-server-anslutning normalt följer en fast procedur: klient (webbläsare) gör begäran, server (ESP32) svarar, ärende stängt. Gjort. Inget händer längre. Om vi bara på något sätt kunde lura webbläsaren att regelbundet begära uppdateringar från ESP32 … och det är precis vad vi kommer att göra med det här javascriptet:

setInterval (function () {var xhttp = new XMLHttpRequest (); xhttp.open ("GET", "/CAMERA", true); xhttp.responseType = "blob"; xhttp.timeout = 500; xhttp.ontimeout = function () {}; xhttp.onload = funktion (e) {if (this.readyState == 4 && this.status == 200) {// se: 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); // skapa ett objekt från bloben document.querySelector ("#camimage"). src = imageUrl; urlCreator.revokeObjectURL (imageurl)}}; xhttp.send ();}, 250);

setInterval tar som parameter en funktion och kör den så ofta (här en gång per 250 ms vilket resulterar i 4 bildrutor/sekund). Funktionen som utförs gör en begäran om en binär "blob" på adressen /CAMERA. Detta hanteras av ESP32-CAM i skissen som (från Randomnerdtutorials):

server.on ("/CAMERA", HTTP_GET, (AsyncWebServerRequest * begäran) {Serial.println ("kameraförfrågan mottagen!"); camera_fb_t * fb = NULL; // esp_err_t res = ESP_OK; size_t _jpg_buf_len = 0; uint8_ * _jpg_buf = NULL; // fånga en ram fb = esp_camera_fb_get (); if (! fb) {Serial.println ("Rambuffert kunde inte förvärvas"); return;} if (fb-> format! = PIXFORMAT_JPEG)/ /redan i detta format från config {bool jpeg_converted = frame2jpg (fb, 80, & _jpg_buf, & _jpg_buf_len); esp_camera_fb_return (fb); fb = NULL; if (! jpeg_converted) {Serial.println ("JPEG -komprimering misslyckades"); return; }} annat {_jpg_buf_len = fb-> len; _jpg_buf = fb-> buf;} //Serial.println(_jpg_buf_len); // skicka den formaterade bildförfrågan-> send_P (200, "image/jpg", _jpg_buf, _jpg_buf_len); // sanering om (fb) {esp_camera_fb_return (fb); fb = NULL; _jpg_buf = NULL;} annars om (_jpg_buf) {gratis (_jpg_buf); _jpg_buf = NULL;}});

De viktiga delarna är att få ramen fb = esp_camera_fb_get () att konvertera den till en-j.webp

Javascript -funktionen väntar sedan på att denna bild ska komma. Sedan tar det bara lite arbete att konvertera den mottagna "bloben" till en url som kan användas som källa för att uppdatera bilden med i html -sidan.

fy, vi är klara!

Steg 4: Idéer och rester

Idéer och rester
Idéer och rester

Målet med detta projekt för mig var att lära mig tillräckligt med webbprogrammering för att ansluta hårdvara till webben. Flera utökningar av detta projekt är möjliga. Här är några idéer:

  • Implementera "riktig" kameraströmning som förklaras här och här och flytta den till en andra server som förklaras här på samma ESP32, men på den andra CPU -kärnan, importera sedan kameraströmmen till html som serveras av den första servern med en … Detta bör resultera i snabbare kamerauppdateringar.
  • Använd åtkomstpunkt (AP) -läget så att roboten är mer fristående som förklaras här.
  • Expandera med batterispänningsmätning, djupa sömnfunktioner etc. Detta är lite svårt för tillfället eftersom AI-Thinker ESP32-CAM inte har många GPIO: er; behöver expansion via uart och till exempel en slavarduino.
  • Konvertera till en kattsökande robot som matar ut kattgodis då och då med tasspressning av en stor knapp, strömma massor av fina kattbilder under dagen …

Kommentera gärna om du gillade eller har frågor och tack för att du läste!

Rekommenderad: