23浏览
查看: 23|回复: 2

[项目] 【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子

[复制链接]
谁不想创建一个完全认证的无用箱呢?自从我在法戈看到一个之后,我当然想要一个
另外,我把它作为 ESP32 的一种“Hello world”练习。

看看它的实际效果:
你需要:
• 一个 ESP32
• 托管在 https://github.com/wiz78/UselessBox 的代码
• 一个 5mm LED
• 一个 220 欧姆电阻
• 一个小型 SPDT 杠杆开关
• 一个微型伺服电机(我使用的是 Miuzei MS18)
• 一些电线
• 4 个用于顶部滑盖的小型 M3 螺丝
• 2 个用于 ESP 阻挡器和 LED 支撑的长 M3 螺丝
• 一个 2A USB 电源 + 微型 USB 线

一些组装提示:
• 使用电阻连接 LED 到 GND 和 GPIO 引脚(例如 16)之间。
• 连接电机到另一个 GND 和不同的 GPIO(例如 18)。
• 连接开关到 GND 和 GPIO 引脚(例如 12)之间。
• 这些是代码中已定义的引脚,当然你可以更改它们。
• 该代码可以进行调整,以启用一个 HTTP 服务器来替换固件,还可以启用其他测试端点。其中一个特别有用,可以用来校准伺服电机组装后的位置:即 curl -o- -X POST http://uselessbox.local/servo?pos=80 - 你需要找到将代码中用于静止位置(臂在盖子下面)、偷看位置(臂部分抬高,打开盖子)和推压位置(足以将开关移到关闭位置)的值输入。

刷写 ESP32:
• 从 Github 下载代码。
• 将 wifi_config-dist.h 重命名为 wifi_config.h。
• 编辑 wifi_config.h 并插入你的 Wi-Fi 设置。
• 安装 Arduino IDE (https://www.arduino.cc/en/software)
• 为 ESP32 设置它(例如 https://medium.com/@pauljoegeorg ... -esp32-34db014a7e65)
• 编译代码并将其上传到 ESP32。
• 在使用电机之前,将 ESP32 与电脑断开连接。
• 按照最后一个“组装提示”中的说明校准伺服电机。一旦你有了正确的要在 UselessBox.ino 的第 13-16 行中输入的值,重新编译并刷写 ESP32。

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图7

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图6

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图5

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图4

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图3

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图2

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图1

驴友花雕  中级技神
 楼主|

发表于 6 小时前

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子

项目代码

  1. #include <ezButton.h>
  2. #include <ESP32Servo.h>
  3. #define OTA_ENABLED 0
  4. const int switchPin = 12;
  5. const int ledPin = 16;
  6. const int motorPin = 18;
  7. ezButton topSwitch(switchPin);
  8. Servo servo;
  9. const int restingPos = 160;
  10. const int peekingPos = 80;
  11. const int intermediatePos = 60;
  12. const int pushingPos = 41;
  13. unsigned int lastActionMillis = 0;
  14. bool firstAction = true;
  15. bool ledOn = false;
  16. void simple();
  17. void slow();
  18. void verySlow();
  19. void slowPeek();
  20. void angry();
  21. void peeking();
  22. typedef void (*actionHandler)();
  23. const actionHandler actions[] = {
  24.   simple,
  25.   slow,
  26.   verySlow,
  27.   slowPeek,
  28.   angry,
  29.   peeking,
  30.   simple,
  31.   simple,
  32.   simple,
  33.   simple,
  34.   slowPeek,
  35.   peeking,
  36.   peeking,
  37.   angry,
  38.   angry,
  39.   angry,
  40. };
  41. constexpr int actionsCount = sizeof( actions ) / sizeof( actions[0] );
  42. #if OTA_ENABLED
  43. // based on https://randomnerdtutorials.com/esp32-over-the-air-ota-programming/
  44. #include <WiFi.h>
  45. #include <WiFiClient.h>
  46. #include <WebServer.h>
  47. #include <ESPmDNS.h>
  48. #include <Update.h>
  49. #include "wifi_config.h"
  50. const char *host = "uselessBox";
  51. const char *otaPage =
  52. "<html>"
  53. "<head>"
  54. "<title>useless box OTA</title>"
  55. "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
  56. "</head>"
  57. "<body>"
  58. "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
  59.    "<input type='file' name='update'>"
  60.         "<input type='submit' value='Update'>"
  61.     "</form>"
  62. "<div id='prg'>progress: 0%</div>"
  63. "<script>"
  64.   "$('form').submit(function(e){"
  65.   "e.preventDefault();"
  66.   "var form = $('#upload_form')[0];"
  67.   "var data = new FormData(form);"
  68.   " $.ajax({"
  69.   "url: '/update',"
  70.   "type: 'POST',"
  71.   "data: data,"
  72.   "contentType: false,"
  73.   "processData:false,"
  74.   "xhr: function() {"
  75.   "var xhr = new window.XMLHttpRequest();"
  76.   "xhr.upload.addEventListener('progress', function(evt) {"
  77.   "if (evt.lengthComputable) {"
  78.   "var per = evt.loaded / evt.total;"
  79.   "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
  80.   "}"
  81.   "}, false);"
  82.   "return xhr;"
  83.   "},"
  84.   "success:function(d, s) {"
  85.   "console.log('success!')"
  86. "},"
  87. "error: function (a, b, c) {"
  88. "}"
  89. "});"
  90. "});"
  91. "</script>"
  92. "</body>"
  93. "</html>";
  94. WebServer server(80);
  95. #endif
  96. void setup()
  97. {
  98. #if OTA_ENABLED
  99.   Serial.begin(115200);
  100.   WiFi.begin(ssid, password);
  101.   for(int i = 0; ( i < 20 ) && ( WiFi.status() != WL_CONNECTED ); i++) {
  102.     delay(500);
  103.     Serial.print(".");
  104.   }
  105.   Serial.println("");
  106.   Serial.print("Connected to ");
  107.   Serial.println(ssid);
  108.   Serial.print("IP address: ");
  109.   Serial.println(WiFi.localIP());
  110.   /*use mdns for host name resolution*/
  111.   if (!MDNS.begin(host)) {
  112.     Serial.println("Error setting up MDNS responder!");
  113.   }
  114.   server.on("/", HTTP_GET, []() {
  115.     server.sendHeader("Connection", "close");
  116.     server.send(200, "text/html", otaPage);
  117.   });
  118.   /*handling uploading firmware file */
  119.   server.on("/update", HTTP_POST, []() {
  120.     server.sendHeader("Connection", "close");
  121.     server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
  122.     ESP.restart();
  123.   }, []() {
  124.     HTTPUpload& upload = server.upload();
  125.     if (upload.status == UPLOAD_FILE_START) {
  126.       Serial.printf("Update: %s\n", upload.filename.c_str());
  127.       if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
  128.         Update.printError(Serial);
  129.       }
  130.     } else if (upload.status == UPLOAD_FILE_WRITE) {
  131.       /* flashing firmware to ESP*/
  132.       if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
  133.         Update.printError(Serial);
  134.       }
  135.     } else if (upload.status == UPLOAD_FILE_END) {
  136.       if (Update.end(true)) { //true to set the size to the current progress
  137.         Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
  138.       } else {
  139.         Update.printError(Serial);
  140.       }
  141.     }
  142.   });
  143.   /* set servo position, useful to calibrate the motor */
  144.   server.on("/servo", HTTP_POST, []() {
  145.     server.sendHeader("Connection", "close");
  146.     server.send(200, "text/plain", "OK\n");
  147.    
  148.     if(server.hasArg("pos")) {
  149.       servo.write(server.arg("pos").toInt());
  150.       delay(300);
  151.     }
  152.   });
  153.   server.on("/action", HTTP_POST, []() {
  154.     server.sendHeader("Connection", "close");
  155.     server.send(200, "text/plain", "OK\n");
  156.    
  157.     if(server.hasArg("num")) {
  158.       int requestedAction = server.arg("num").toInt();
  159.       actions[ requestedAction % ( actionsCount + 1 ) ]();
  160.     } else if(server.hasArg("peek"))
  161.       peekAfterwards();
  162.   });
  163.   server.begin();
  164. #endif
  165.   topSwitch.setDebounceTime(100);
  166.   pinMode(ledPin, OUTPUT);
  167.   setLed(false);
  168.   servo.setPeriodHertz(50);
  169.   servo.attach(motorPin);
  170.   servo.write(restingPos);
  171. }
  172. void loop()
  173. {
  174. #if OTA_ENABLED
  175.   server.handleClient();
  176. #endif
  177.   topSwitch.loop();
  178.   if(topSwitch.getState() == LOW) {
  179.     int action, maxAction;
  180.     unsigned long sinceLastAction = millis() - lastActionMillis;
  181.    
  182.     if(!lastActionMillis)
  183.       srandom(millis());
  184.     if(sinceLastAction > 60 * 5 * 1000)
  185.       firstAction = true;
  186.     if(firstAction)
  187.       action = 0;
  188.     else
  189.       action = random(0, actionsCount - 1);
  190.     actions[ action ]();
  191.     if(!firstAction && (sinceLastAction < 5000) && (random(1, 10) > 6))
  192.       peekAfterwards();
  193.     lastActionMillis = millis();
  194.     firstAction = false;
  195.   }
  196.   
  197.   if(ledOn)
  198.     setLed(false);
  199.   delay(20);
  200. }
  201. int stepFromTo(int from, int to)
  202. {
  203.   return (to > from) ? 1 : -1;
  204. }
  205. void simple()
  206. {
  207.   servo.write(pushingPos);
  208.   delay(250);
  209.   servo.write(restingPos);
  210. }
  211. void slow()
  212. {
  213.   for(int i = restingPos; i != pushingPos; i += stepFromTo(restingPos, pushingPos)) {
  214.     servo.write(i);
  215.     delay(10);
  216.   }
  217.   servo.write(intermediatePos);
  218.   delay(100);
  219.   servo.write(pushingPos);
  220.   delay(100);
  221.   servo.write(restingPos);
  222. }
  223. void verySlow()
  224. {
  225.   for(int i = restingPos; i != pushingPos; i += stepFromTo(restingPos, pushingPos)) {
  226.     servo.write(i);
  227.     delay(30);
  228.   }
  229.   servo.write(intermediatePos);
  230.   delay(100);
  231.   servo.write(pushingPos);
  232.   delay(150);
  233.   servo.write(restingPos);
  234. }
  235. void slowPeek()
  236. {
  237.   for(int i = restingPos; i != peekingPos; i += stepFromTo(restingPos, peekingPos)) {
  238.     servo.write(i);
  239.     delay(10);
  240.   }
  241.    
  242.   servo.write(peekingPos);
  243.   delay(500);
  244.   servo.write(pushingPos);
  245.   delay(250);
  246.   servo.write(restingPos);
  247. }
  248. void angry()
  249. {
  250.   setLed(true);
  251.   for(int i = 0; i < 3; i++) {
  252.     servo.write(pushingPos);
  253.     delay(250);
  254.     servo.write(peekingPos);
  255.     delay(200);
  256.   }
  257.   servo.write(restingPos);
  258.   delay(200);
  259. }
  260. void peeking()
  261. {
  262.   servo.write(peekingPos);
  263.   setLed(true);
  264.   delay(250);
  265.   servo.write(pushingPos);
  266.   delay(250);
  267.   servo.write(restingPos);
  268.   delay(200);
  269. }
  270. void peekAfterwards()
  271. {
  272.   setLed(true);
  273.   delay(100);
  274.   servo.write(peekingPos);
  275.   delay(1500);
  276.   servo.write(restingPos);
  277. }
  278. void setLed(bool on)
  279. {
  280.   digitalWrite(ledPin, on ? HIGH : LOW);
  281.   ledOn = on;
  282. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 6 小时前

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子
【Arduino 动手做】ESP32 的一种“Hello world”练习:无聊盒子
项目链接:https://makerworld.com/zh/models/76853
项目作者:Wiz_78

项目代码:https://github.com/wiz78/UselessBox
3D 文件:https://makerworld.com/zh/models ... box#profileId-81310
升级手臂:https://makerworld.com/zh/models ... ox#profileId-669999
带更强的铰链: https://makerworld.com/zh/models ... ge#profileId-442597

【Arduino 动手做】ESP32 的“Hello world”练习:无聊盒子图1

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail