Peter Rusňak
Published © GPL3+

Smars rc rover Esp32 360 degree servo

The popular 3d printed chassis smars got an update- continuos servos and some Esp32 power!

AdvancedFull instructions provided2 hours561
Smars rc rover Esp32 360 degree servo

Things used in this project

Hardware components

Espressif ESP32 Development Board - Developer Edition
Espressif ESP32 Development Board - Developer Edition
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×1
mp1504en buck converter
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Mastech MS8217 Autorange Digital Multimeter
Digilent Mastech MS8217 Autorange Digital Multimeter
Premium Female/Male Extension Jumper Wires, 40 x 6" (150mm)
Premium Female/Male Extension Jumper Wires, 40 x 6" (150mm)

Story

Read more

Custom parts and enclosures

3d files

Code

code

C/C++
#include <WiFi.h>
#include <WebServer.h>
#include <ESP32Servo.h>

const char* AP_SSID     = "SMARS-Rover";
const char* AP_PASSWORD = "rover1234";

#define SERVO_LEFT_PIN  13
#define SERVO_RIGHT_PIN 12
#define LEFT_STOP       92
#define RIGHT_STOP      92
#define DEADZONE        0.08f

WebServer server(80);
Servo servoLeft, servoRight;

const char B64[] =
"PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PG1ldGEgbmFtZT0ndmlld3BvcnQnIGNvbnRlbnQ9"
"J3dpZHRoPWRldmljZS13aWR0aCxpbml0aWFsLXNjYWxlPTEsdXNlci1zY2FsYWJsZT1ubyc+PHRp"
"dGxlPlNNQVJTPC90aXRsZT48c3R5bGU+Kntib3gtc2l6aW5nOmJvcmRlci1ib3g7bWFyZ2luOjA7"
"cGFkZGluZzowfWJvZHl7YmFja2dyb3VuZDojMTExO2NvbG9yOiNmZmY7Zm9udC1mYW1pbHk6c2Fu"
"cy1zZXJpZjtkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246cm93O2FsaWduLWl0ZW1zOmNlbnRl"
"cjtqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyO2hlaWdodDoxMDB2aDtnYXA6MzBweDtvdmVyZmxvdzpo"
"aWRkZW47dXNlci1zZWxlY3Q6bm9uZX1oMntwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MTJweDtsZWZ0"
"OjUwJTt0cmFuc2Zvcm06dHJhbnNsYXRlWCgtNTAlKTtmb250LXNpemU6MTVweDtsZXR0ZXItc3Bh"
"Y2luZzoycHg7Y29sb3I6IzRhZjt0ZXh0LXRyYW5zZm9ybTp1cHBlcmNhc2V9I2N0cmx7ZGlzcGxh"
"eTpmbGV4O2dhcDo2MHB4fS5wYWR7cG9zaXRpb246cmVsYXRpdmU7d2lkdGg6MTEwcHg7aGVpZ2h0"
"OjIwMHB4O2JhY2tncm91bmQ6IzIyMjtib3JkZXItcmFkaXVzOjU1cHg7Ym9yZGVyOjJweCBzb2xp"
"ZCAjNDQ0O3RvdWNoLWFjdGlvbjpub25lfS50aHVtYntwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDo1"
"MnB4O2hlaWdodDo1MnB4O2JvcmRlci1yYWRpdXM6NTAlO2JhY2tncm91bmQ6IzRhZjtsZWZ0OjI5"
"cHg7cG9pbnRlci1ldmVudHM6bm9uZX0ubGJse3RleHQtYWxpZ246Y2VudGVyO2ZvbnQtc2l6ZTox"
"MXB4O2NvbG9yOiM1NTU7bWFyZ2luLXRvcDo1cHg7bGV0dGVyLXNwYWNpbmc6MXB4fTwvc3R5bGU+"
"PC9oZWFkPjxib2R5PjxoMj5TTUFSUzwvaDI+PGRpdiBpZD0nY3RybCc+PGRpdj48ZGl2IGNsYXNz"
"PSdwYWQnIGlkPSdwTCc+PGRpdiBjbGFzcz0ndGh1bWInIGlkPSd0TCc+PC9kaXY+PC9kaXY+PGRp"
"diBjbGFzcz0nbGJsJz5MRUZUPC9kaXY+PC9kaXY+PGRpdj48ZGl2IGNsYXNzPSdwYWQnIGlkPSdw"
"Uic+PGRpdiBjbGFzcz0ndGh1bWInIGlkPSd0Uic+PC9kaXY+PC9kaXY+PGRpdiBjbGFzcz0nbGJs"
"Jz5SSUdIVDwvZGl2PjwvZGl2PjwvZGl2PjxzY3JpcHQ+dmFyIFBBRF9IPTIwMCxUUj0yNixUUkFD"
"Sz0xNDgsdGlkPXtMOm51bGwsUjpudWxsfSx2YWw9e0w6MCxSOjB9LHBMLHBSO2Z1bmN0aW9uIGlu"
"aXQoKXtwTD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncEwnKTtwUj1kb2N1bWVudC5nZXRFbGVt"
"ZW50QnlJZCgncFInKTtzZXRUaHVtYignTCcsMCk7c2V0VGh1bWIoJ1InLDApO3NldEludGVydmFs"
"KHNlbmQsODApO31mdW5jdGlvbiBzZXRUaHVtYihzLHYpe3ZhciB0aD1kb2N1bWVudC5nZXRFbGVt"
"ZW50QnlJZCgndCcrcyk7dGguc3R5bGUudG9wPSgoUEFEX0gvMiktdiooVFJBQ0svMiktVFIpKydw"
"eCc7dGguc3R5bGUuYmFja2dyb3VuZD1NYXRoLmFicyh2KTwwLjA1PycjNGFmJzonI2ZhNCc7dmFs"
"W3NdPXY7fWZ1bmN0aW9uIHNlbmQoKXt2YXIgeD1uZXcgWE1MSHR0cFJlcXVlc3QoKTt4Lm9wZW4o"
"J0dFVCcsJy9kcml2ZT9sPScrdmFsLkwudG9GaXhlZCgyKSsnJnI9Jyt2YWwuUi50b0ZpeGVkKDIp"
"LHRydWUpO3guc2VuZCgpO31mdW5jdGlvbiBjYWxjVih5LGlkKXt2YXIgcj1kb2N1bWVudC5nZXRF"
"bGVtZW50QnlJZChpZCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7dmFyIGR5PXktKHIudG9wK1BB"
"RF9ILzIpO3ZhciBtPVRSQUNLLzI7ZHk9TWF0aC5tYXgoLW0sTWF0aC5taW4obSxkeSkpO3JldHVy"
"biAtZHkvbTt9ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsZnVuY3Rpb24o"
"ZSl7ZS5wcmV2ZW50RGVmYXVsdCgpO2Zvcih2YXIgaT0wO2k8ZS5jaGFuZ2VkVG91Y2hlcy5sZW5n"
"dGg7aSsrKXt2YXIgdD1lLmNoYW5nZWRUb3VjaGVzW2ldO2lmKHBMLmNvbnRhaW5zKHQudGFyZ2V0"
"KSl0aWQuTD10LmlkZW50aWZpZXI7ZWxzZSBpZihwUi5jb250YWlucyh0LnRhcmdldCkpdGlkLlI9"
"dC5pZGVudGlmaWVyO319LHtwYXNzaXZlOmZhbHNlfSk7ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5l"
"cigndG91Y2htb3ZlJyxmdW5jdGlvbihlKXtlLnByZXZlbnREZWZhdWx0KCk7Zm9yKHZhciBpPTA7"
"aTxlLnRvdWNoZXMubGVuZ3RoO2krKyl7dmFyIHQ9ZS50b3VjaGVzW2ldO2lmKHQuaWRlbnRpZmll"
"cj09PXRpZC5MKXNldFRodW1iKCdMJyxjYWxjVih0LmNsaWVudFksJ3BMJykpO2Vsc2UgaWYodC5p"
"ZGVudGlmaWVyPT09dGlkLlIpc2V0VGh1bWIoJ1InLGNhbGNWKHQuY2xpZW50WSwncFInKSk7fX0s"
"e3Bhc3NpdmU6ZmFsc2V9KTtkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsZnVu"
"Y3Rpb24oZSl7Zm9yKHZhciBpPTA7aTxlLmNoYW5nZWRUb3VjaGVzLmxlbmd0aDtpKyspe3ZhciB0"
"PWUuY2hhbmdlZFRvdWNoZXNbaV07aWYodC5pZGVudGlmaWVyPT09dGlkLkwpe3RpZC5MPW51bGw7"
"c2V0VGh1bWIoJ0wnLDApO31lbHNlIGlmKHQuaWRlbnRpZmllcj09PXRpZC5SKXt0aWQuUj1udWxs"
"O3NldFRodW1iKCdSJywwKTt9fX0pO2luaXQoKTs8L3NjcmlwdD48L2JvZHk+PC9odG1sPg==";

String decodeB64(const char* src) {
  const char* b64c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  String out = "";
  int val = 0, valb = -8;
  for (const char* p = src; *p; p++) {
    const char* pos = strchr(b64c, *p);
    if (!pos) continue;
    val = (val << 6) + (pos - b64c);
    valb += 6;
    if (valb >= 0) { out += (char)((val >> valb) & 0xFF); valb -= 8; }
  }
  return out;
}

void setLeft(float v) {
  if (fabs(v) < DEADZONE) { servoLeft.write(LEFT_STOP); return; }
  servoLeft.write(LEFT_STOP - (int)(v * 89));
}

void setRight(float v) {
  if (fabs(v) < DEADZONE) { servoRight.write(RIGHT_STOP); return; }
  servoRight.write(RIGHT_STOP + (int)(v * 89));
}

void stopAll() {
  servoLeft.write(LEFT_STOP);
  servoRight.write(RIGHT_STOP);
}

void setup() {
  Serial.begin(115200);
  servoLeft.attach(SERVO_LEFT_PIN);
  servoRight.attach(SERVO_RIGHT_PIN);
  servoLeft.write(LEFT_STOP);
  servoRight.write(RIGHT_STOP);
  delay(500);
  stopAll();

  WiFi.softAP(AP_SSID, AP_PASSWORD);
  Serial.println(WiFi.softAPIP());

  String page = decodeB64(B64);
  server.on("/", [page]() { server.send(200, "text/html", page); });
  server.on("/drive", []() {
    float l = server.arg("l").toFloat();
    float r = server.arg("r").toFloat();
    setLeft(l);
    setRight(r);
    server.send(200, "text/plain", "ok");
  });
  server.begin();
  Serial.println("Ready: http://192.168.4.1");
}

void loop() {
  server.handleClient();
}

Credits

Peter Rusňak
2 projects • 0 followers
High school student, who is interested in robotics, WRO competitions and ai development

Comments