LEGO扩展教程
============

.. _1-足球机器人:

1. 足球机器人
-------------

.. _11-实验简介:

1.1. 实验简介：
~~~~~~~~~~~~~~~

足球运动是一种大家非常喜爱的运动。让
`机器人 <https://baike.baidu.com/item/机器人/888>`__\ 去踢足球，听起来像天方夜谭似的。机器人也能去踢足球？
是的，足球机器人可以做到像我们人一样去组成团队进行踢足球比赛，比如：一年一度的RoboCup机器人世界杯---RoboCup足球赛等。在本实验中，我们利用乐高积木搭建了一款足球机器人，并且使用足球机器人把小足球送进足球门里。

.. _12-足球机器人形态安装步骤:

1.2. 足球机器人形态安装步骤
~~~~~~~~~~~~~~~~~~~~~~~~~~~

先将两个光敏传感器拆下

|img|

--------------

安装所需零件

|image1|

--------------

安装

|image2|

--------------

完成

|image3|

--------------

安装所需零件

|image4|

--------------

安装

|image5|

--------------

完成

|image6|

--------------

安装所需零件

|image7|

--------------

安装

|image8|

--------------

完成

|image9|

--------------

安装所需零件

|image10|

--------------

安装

|image11|

--------------

完成

|image12|

--------------

安装所需零件

|image13|

--------------

安装

|image14|

--------------

完成

|image15|

--------------

安装所需零件

|image16|

--------------

安装（注意红圈内凸起朝右）

|image17|

--------------

完成

|image18|

--------------

安装所需零件

|image19|

--------------

安装

|image20|

--------------

完成

|image21|

--------------

安装所需零件

|image22|

--------------

安装（注意调整夹爪角度，使其闭合朝前）

|image23|

--------------

完成

|image24|

--------------

安装所需零件

|image25|

--------------

**注意在安装前需要先调节舵机角度为180度**

**将舵机的线接到PCB上板的S2接口，如下表:**

====== =========
舵机   小车PCB板
====== =========
棕线   G
红线   5V
橙黄线 S2（A0）
====== =========

**Arduino代码：**

.. code:: c++

   #include <Servo.h>
   Servo myservo;  // create servo object to control a servo

   void setup() {
     myservo.attach(A0);  // attaches the servo on pin A0 to the servo object
     myservo.write(0);  // tell servo to go to position
     delay(1000);
     myservo.write(90);  // tell servo to go to position
     delay(1000);
     myservo.write(180);  // tell servo to go to position
     delay(1000);
   }

   void loop() {
     
   }

上面的Arduino代码在资料中有提供，打开舵机的调整代码并烧录到Beetlebot的主板，完成。代码如下图位置:

|image26|

**KidsBlock(Scratch)代码：**

也可以使用Scratch代码来调整舵机初始角度：

|image27|

KidsBlock(Scratch)代码在资料中也有提供，打开舵机的调整代码并烧录到Beetlebot的主板，完成。代码如下图位置:

|image28|

安装（齿轮安装时保持夹爪为闭合朝前状态）

|image29|

--------------

完成

|image30|

--------------

安装所需零件

|image31|

--------------

安装

|image32|

--------------

完成

|image33|

--------------

安装所需零件

|image34|

--------------

安装

|image35|

--------------

完成

|image36|

--------------

足球小将形态完成

|image37|

--------------

乐高舵机接线图

**将舵机的线接到PCB上板的S2接口，如下表:**

====== =========
舵机   小车PCB板
====== =========
棕线   G
红线   5V
橙黄线 S2（A0）
====== =========

|image38|

.. _13-足球门安装步骤:

1.3. 足球门安装步骤
~~~~~~~~~~~~~~~~~~~

安装所需零件

|image39|

--------------

安装

|image40|

--------------

完成

|image41|

--------------

安装所需零件

|image42|

--------------

安装

|image43|

--------------

完成

|image44|

--------------

安装所需零件

|image45|

--------------

安装

|image46|

--------------

完成

|image47|

--------------

.. _14-arduino代码:

1.4. Arduino代码：
~~~~~~~~~~~~~~~~~~

**ESP8266代码**

|Img|

**特别注意：** 需要先将项目代码

|image48|\ 中的用户Wifi名称和用户Wifi密码改成你们自己的Wifi名称和Wifi密码。

ESP8266串口WIFI ESP-01模块的UTXD引脚是由Arduino
Nano主板的IO口RX（0）控制，URXD引脚是由Arduino
Nano主板的IO口TX（1）控制。

.. code:: c++

   //**********************************************************************************
   /*
   ESP8266_Code
   */
   // generated by KidsBlock
   #include <Arduino.h>
   #include <ESP8266WiFi.h>
   #include <ESP8266mDNS.h>
   #include <WiFiClient.h>
   //#include <WiFi.h>

   #ifndef STASSID
   #define STASSID "ChinaNet-2.4G-0DF0"  //the name of user's Wifi
   #define STAPSK  "ChinaNet@233"       //the password of the user's wifi
   #endif
   const char* ssid = STASSID;
   const char* password = STAPSK;

   //IPAddress local_IP(192,168,4,22);
   //IPAddress gateway(192,168,4,22);
   //IPAddress subnet(255,255,255,0);
   //
   //const char *ssid = "ESP8266_AP_TEST";
   //const char *password = "12345678";

   WiFiServer server(80);
   String unoData = "";
   int ip_flag = 0;
   int ultra_state = 1;
   String ip_str;


   void setup() {
     Serial.begin(9600); 
   //   WiFi.mode(WIFI_AP); //设置工作在AP模式
   //
   //  WiFi.softAPConfig(local_IP, gateway, subnet); //设置AP地址
   //  while(!WiFi.softAP(ssid, password)){}; //启动AP
   //  Serial.println("AP启动成功");
   //
   //  Serial.print("IP address: ");
   //  Serial.println(WiFi.softAPIP()); // 打印IP地址
   //
   //  WiFi.softAPsetHostname("myHostName"); //设置主机名
   //  Serial.print("HostName: ");
   //  Serial.println(WiFi.softAPgetHostname()); //打印主机名
   //
   //  Serial.print("mac Address: ");
   //  Serial.println(WiFi.softAPmacAddress()); //打印mac地址

     WiFi.mode(WIFI_STA);
     WiFi.begin(ssid, password);
     while (WiFi.status() != WL_CONNECTED) {
       delay(500);
       Serial.print(".");
     }
     Serial.print("IP ADDRESS: ");
     Serial.println(WiFi.localIP());
     if (!MDNS.begin("esp8266")) {
       //Serial.println("Error setting up MDNS responder!");
       while (1) {
         delay(1000);
       }
     }
    // Serial.println("mDNS responder started");
     server.begin();
     //Serial.println("TCP server started");
     MDNS.addService("http", "tcp", 80);
     ip_flag = 1;
   }

   void loop() {
     //Serial.println(WiFi.softAPgetStationNum()); //打印客户端连接数
     if(ip_flag == 1)
     {
       for(int i=3; i>0; i--)
       {
         Serial.print("IP: ");
         Serial.print(WiFi.localIP());
         Serial.println('#');
         delay(500);
       }
       ip_flag = 0;
       
     }
       MDNS.update();
       WiFiClient client = server.available();
       if (!client) {
         return;
       }
       //Serial.println("");
       while (client.connected() && !client.available()) {
         delay(1);
       }
       String req = client.readStringUntil('\r');
       int addr_start = req.indexOf(' ');
       int addr_end = req.indexOf(' ', addr_start + 1);
       if (addr_start == -1 || addr_end == -1) {
         //Serial.print("Invalid request: ");
         //Serial.println(req);
         return;
       }
       req = req.substring(addr_start + 1, addr_end);
       int len_val = String(req).length();
       String M_req = String(req).substring(0,6);
       //Serial.println(M_req);
       if(M_req == "/btn/u")
       {
         String s_M_req = String(req).substring(5,len_val);
         Serial.print(s_M_req);
         Serial.print("#");
       }
       if(M_req == "/btn/v")
       {
         String s_M_req = String(req).substring(5,len_val);
         Serial.print(s_M_req);
         Serial.print("#");
       }
       client.flush();
       String s;
       if (req == "/") {
         IPAddress ip = WiFi.localIP();
         String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
         s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
         s += ipStr;
         s += "</html>\r\n\r\n";
         //Serial.println("Sending 200");
         Serial.println(WiFi.localIP());
         Serial.write('*');
         client.println(WiFi.localIP());
         ip_flag = 0;
       }
       else if(req == "/btn/F")
       {
         Serial.write('F');
         client.println(F("F"));
       }
       else if(req == "/btn/B")
       {
         Serial.write('B');
         client.println(F("B"));
       }
       else if(req == "/btn/L")
       {
         Serial.write('L');
         client.println(F("L"));
       }
       else if(req == "/btn/R")
       {
         Serial.write('R');
         client.println(F("R"));
       }
       else if(req == "/btn/S")
       {
         Serial.write('S');
         client.println(F("S"));
       }
       else if(req == "/btn/a")
       {
         Serial.write('a');
         client.println(F("a"));
       }
       else if(req == "/btn/b")
       {
         Serial.write('b');
         client.println(F("b"));
       }
       else if(req == "/btn/c")
       {
         Serial.write('c');
         client.println(F("c"));
       }
       else if(req == "/btn/d")
       {
         Serial.write('d');
         client.println(F("d"));
       }
       else if(req == "/btn/e")
       {
         Serial.write('e');
         client.println(F("e"));
       }
       else if(req == "/btn/f")
       {
         Serial.write('f');
         client.println(F("f"));
       }
       else if(req == "/btn/g")
       {
         Serial.write('g');
         client.println(F("g"));
       }
       else if(req == "/btn/z")
       {
         Serial.write('z');
         client.println(F("z"));
       }
       else if(req == "/btn/i")
       {
         Serial.write('i');
         client.println(F("i"));
       }
       else if(req == "/btn/j")
       {
         Serial.write('j');
         client.println(F("j"));
       }
       else if(req == "/btn/k")
       {
         Serial.write('k');
         client.println(F("k"));
       }
       else if(req == "/btn/y")
       {
         Serial.write('y');
         client.println(F("y"));
       }
       else if(req == "/btn/l")
       {
         Serial.write('l');
         client.println(F("l"));
       }
       else if(req == "/btn/m")
       {
         Serial.write('m');
         client.println(F("m"));
       }
       else if(req == "/btn/n")
       {
         Serial.write('n');
         client.println("n");
       }
       else if(req == "/btn/o")
       {
         Serial.write('o');
         client.println(F("o"));
       }
       else if(req == "/btn/p")
       {
         Serial.write('p');
         client.println(F("p"));
       }
       else if(req == "/btn/q")
       {
         Serial.write('q');
         client.println("q");
       }
       else if(req == "/btn/x")
       {
         Serial.write('x');
         client.println(F("x"));
       }
       else if(req == "/btn/1")
       {
         Serial.write('1');
         client.println(F("1"));
       }
       else if(req == "/btn/2")
       {
         Serial.write('2');
         client.println("2");
       }
       else if(req == "/btn/3")
       {
         Serial.write('3');
         client.println(F("3"));
       }
       else if(req == "/btn/4")
       {
         Serial.write('4');
         client.println("4");
       }
       else if(req == "/btn/5")
       {
         Serial.write('5');
         client.println(F("5"));
       }
       else if(req == "/btn/0")
       {
         Serial.write('0');
         client.println("0");
       }
       else {
         //s = "HTTP/1.1 404 Not Found\r\n\r\n";
         //Serial.println("Sending 404");
       }

       client.print(F("IP : "));
       client.println(WiFi.localIP());
   }
   //**********************************************************************************

Wifi名称和Wifi密码修改后，确保USB转ESP-01S
WIFI模块串口测试扩展板上的拨码开关已经拨到Uart Download
端，并且也确定USB转ESP-01S
WIFI模块串口测试扩展板已经插入电脑的USB口。然后按照 **Arduino 教程中的
Project 16**
中的方法设置板型和COM口，IDE右下角显示对应板型和COM口，再点击\ |image49|\ 将ESP8266
代码上传到ESP8266串口WIFI
ESP-01模块上，上传成功。（注意：如果上传失败，在板型和COM口没问题情况下，将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来再次插到电脑的USB口)

ESP8266 代码上传成功后，先将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来，再将ESP8266串口WIFI
ESP-01模块从USB转ESP-01S WIFI模块串口测试扩展板上拔下来。

**Arduino Nano 实验代码**

|image50|

**注意：**
打开IDE后，一定要先设置好板型和COM口。如果家里没有WIFI需要打开手机热点共享WIFI。

.. code:: c++

   #include <Servo.h>
   Servo lgservo;
   #define ML 4
   #define ML_PWM 6
   #define MR 2
   #define MR_PWM 5
   #define servo2 A0

   char val;
   char wifiData;

   void setup() {
     Serial.begin(9600);
     pinMode(ML, OUTPUT);
     pinMode(ML_PWM, OUTPUT);
     pinMode(MR, OUTPUT);
     pinMode(MR_PWM, OUTPUT);
     
     lgservo.attach(A0);
     lgservo.write(180);
     delay(1000);
     lgservo.write(160);
   }

   void loop() {
     if(Serial.available() > 0)
     {
       val = Serial.read();
       Serial.print(val);
     }
     switch(val)
     {
       case 'F': car_forward(); break;
       case 'B': car_back(); break;
       case 'L': car_left(); break;
       case 'R': car_right(); break;
       case 'S': car_stop(); break;
       case 'p': lgservo.write(180); break;
       case 'x': lgservo.write(160); break;
     }
   }


   void car_forward()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,127);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,127);
   }

   void car_back()
   {
     digitalWrite(ML,HIGH);
     analogWrite(ML_PWM,127);
     digitalWrite(MR,HIGH);
     analogWrite(MR_PWM,127);
   }

   void car_left()
   {
     digitalWrite(ML,HIGH);
     analogWrite(ML_PWM,150);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,105);
   }

   void car_right()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,105);
     digitalWrite(MR,HIGH);
     analogWrite(MR_PWM,150);
   }

   void car_stop()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,0);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,0);
   }

--------------

.. _15-kidsblockscratch代码:

1.5. KidsBlock(Scratch)代码:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**ESP8266 代码：**

|image51|

**注意：** 如果家里没有WIFI，需要打开手机热点共享WIFI.

|image-20230703132208975|

**特别注意：** 需要将ESP8266代码\ |image52|

中的Wifi名称和Wifi密码改成你们自己的Wifi名称和Wifi密码。

A. Wifi名称和Wifi密码修改后，确保USB转ESP-01S
WIFI模块串口测试扩展板上的拨码开关已经拨到Uart Download
端，并且也确定USB转ESP-01S
WIFI模块串口测试扩展板已经插入电脑的USB口，然后点击kidsblock软件上的“\ **上传**\ ”
按钮 。将ESP8266代码上传到ESP8266串口WIFI
ESP-01模块上，上传成功。（注意：如果上传失败，在板型和COM口没问题下，将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来再次插到电脑的USB口）

|image53|

B. ESP8266代码上传成功后，先将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来，再将ESP8266串口WIFI
ESP-01模块从USB转ESP-01S WIFI模块串口测试扩展板上拔下来。

**USB线连接电脑和Arduino Nano主板：**

|image54|

**Beetlebot页面设置:**

更换开发板，点击\ |image-20230703133342925|\ 进入设备选择页面，点击
“\ **套件**\ ”，选中 **Beetlebot 3in1 Robot for Arduino** ，单击“连接”。

|image-20230703133422037|

|image55|

|image-20230703133451215|

**Arduino Nano实验代码：**

|image56|

|image57|

--------------

.. _16-实验场景:

1.6. 实验场景：
~~~~~~~~~~~~~~~

1. 将足球门（乐高造型已搭好）放在地上某个固定的位置，APP连上WiFi。

2.
将小足球放在足球机器人的夹子中间，按住按钮\ |image58|\ 使夹子夹住小足球，同时操作小车方向按钮\ |image59|\ 使足球机器人把小足球送到离足球门一小段距离处再松开按钮\ |image60|\ 。这样，小足球掉在地上且往前滚，看看小足球是否会滚进足球门里？如果没有，就反复上面的操作，使小足球最终进入足球门里。

3.
如果你们小伙伴们也拥有这款足球机器人，可以和小伙伴们一起进行足球比赛，每一个足球机器人都夹着小足球，大家都操作各自的APP上的小车方向按钮，看看谁能最终把足球送到足球门里。

.. _2-投石攻城车:

2. 投石攻城车
-------------

.. _21-实验简介:

2.1. 实验简介
~~~~~~~~~~~~~

投石攻城车在古代主要用于围攻和防守要塞，主要是用木头制作的，是利用配重物的重力发射，把石头抛出去。我们也制作了一款投石攻城车，是由车和乐高积木搭建而成的，车上装有舵机和齿轮，长臂末端有乐高搭建的凹槽是用于装投射物。\ `发射 <https://baike.baidu.com/item/发射/7776886>`__\ 时，舵机转动带动齿轮把长臂向后推，把投射物放入凹槽中,当舵机转动一定角度带动齿轮把长臂完全升起时，投射物从凹槽中飞出。

.. _22-攻城战车形态安装步骤:

2.2. 攻城战车形态安装步骤
~~~~~~~~~~~~~~~~~~~~~~~~~

安装所需零件

|image61|

--------------

安装

|image62|

--------------

完成

|image63|

--------------

安装所需零件

|image64|

--------------

安装

|image65|

--------------

完成

|image66|

--------------

安装所需零件

|image67|

--------------

安装

|image68|

--------------

完成

|image69|

--------------

安装所需零件

|image70|

--------------

安装

|image71|

--------------

完成

|image72|

--------------

安装所需零件

|image73|

--------------

安装

|image74|

--------------

完成

|image75|

--------------

安装所需零件

|image76|

--------------

安装

|image77|

--------------

完成

|image78|

--------------

安装所需零件

|image79|

--------------

安装

|image80|

--------------

完成

|image81|

--------------

安装所需零件

|image82|

--------------

安装

|image83|

--------------

完成

|image84|

--------------

安装所需零件

|image85|

--------------

安装

|image86|

--------------

完成

|image87|

--------------

安装所需零件

|image88|

--------------

安装

|image89|

--------------

完成

|image90|

--------------

安装所需零件

|image91|

--------------

安装

|image92|

--------------

完成

|image93|

--------------

安装所需零件

|image94|

--------------

安装

|image95|

--------------

完成

|image96|

--------------

安装所需零件

|image97|

--------------

安装

|image98|

--------------

完成

|image99|

--------------

安装所需零件

|image100|

--------------

安装

|image101|

--------------

完成

|image102|

--------------

安装所需零件

|image103|

--------------

安装

|image104|

--------------

完成

|image105|

--------------

安装所需零件

|image106|

--------------

安装

|image107|

--------------

完成

|image108|

--------------

安装所需零件

|image109|

--------------

**安装前需调节舵机角度为0°**

将舵机的线接到PCB上板的S2接口，如下表:

====== =========
舵机   小车PCB板
====== =========
棕线   G
红线   5V
橙黄线 S2（A0）
====== =========

**Arduino代码：**

.. code:: c++

   #include <Servo.h>
   Servo myservo;  // create servo object to control a servo

   void setup() {
     myservo.attach(A0);  // attaches the servo on pin A0 to the servo object
     myservo.write(0);  // tell servo to go to position
     delay(1000);
     myservo.write(90);  // tell servo to go to position
     delay(1000);
     myservo.write(0);  // tell servo to go to position
     delay(1000);
   }

   void loop() {

   }

上面的Arduino代码在资料中有提供，打开舵机的调整代码并烧录到Beetlebot的主板，完成。代码如下图位置。

|image110|

**KidsBlock(Scratch)代码：**

也可以使用下面的Scratch-KidsBlock代码来调整舵机初始化角度。

|image111|

KidsBlock(Scratch)代码在资料中也有提供，打开舵机的调整代码并烧录到Beetlebot的主板，完成。代码如下图位置:

|image112|

--------------

安装（安装姿态与右图保持一致）

|image113|

--------------

完成

|image114|

--------------

安装所需零件

|image115|

--------------

安装

|image116|

--------------

完成

|image117|

--------------

舵机接线图

|image118|

.. _23-arduino代码:

2.3. Arduino代码
~~~~~~~~~~~~~~~~

**ESP8266代码：**

|image119|

**特别注意：** 需要先将项目代码

|image120|\ 中的用户Wifi名称和用户Wifi密码改成你们自己的Wifi名称和Wifi密码。

ESP8266串口WIFI ESP-01模块的UTXD引脚是由Arduino
Nano主板的IO口RX（0）控制，URXD引脚是由Arduino
Nano主板的IO口TX（1）控制。

.. code:: c++

   //**********************************************************************************
   /*
   ESP8266_Code
   */
   // generated by KidsBlock
   #include <Arduino.h>
   #include <ESP8266WiFi.h>
   #include <ESP8266mDNS.h>
   #include <WiFiClient.h>
   //#include <WiFi.h>

   #ifndef STASSID
   #define STASSID "ChinaNet-2.4G-0DF0"  //the name of user's Wifi
   #define STAPSK  "ChinaNet@233"       //the password of the user's wifi
   #endif
   const char* ssid = STASSID;
   const char* password = STAPSK;

   //IPAddress local_IP(192,168,4,22);
   //IPAddress gateway(192,168,4,22);
   //IPAddress subnet(255,255,255,0);
   //
   //const char *ssid = "ESP8266_AP_TEST";
   //const char *password = "12345678";

   WiFiServer server(80);
   String unoData = "";
   int ip_flag = 0;
   int ultra_state = 1;
   String ip_str;


   void setup() {
     Serial.begin(9600); 
   //   WiFi.mode(WIFI_AP); //设置工作在AP模式
   //
   //  WiFi.softAPConfig(local_IP, gateway, subnet); //设置AP地址
   //  while(!WiFi.softAP(ssid, password)){}; //启动AP
   //  Serial.println("AP启动成功");
   //
   //  Serial.print("IP address: ");
   //  Serial.println(WiFi.softAPIP()); // 打印IP地址
   //
   //  WiFi.softAPsetHostname("myHostName"); //设置主机名
   //  Serial.print("HostName: ");
   //  Serial.println(WiFi.softAPgetHostname()); //打印主机名
   //
   //  Serial.print("mac Address: ");
   //  Serial.println(WiFi.softAPmacAddress()); //打印mac地址

     WiFi.mode(WIFI_STA);
     WiFi.begin(ssid, password);
     while (WiFi.status() != WL_CONNECTED) {
       delay(500);
       Serial.print(".");
     }
     Serial.print("IP ADDRESS: ");
     Serial.println(WiFi.localIP());
     if (!MDNS.begin("esp8266")) {
       //Serial.println("Error setting up MDNS responder!");
       while (1) {
         delay(1000);
       }
     }
    // Serial.println("mDNS responder started");
     server.begin();
     //Serial.println("TCP server started");
     MDNS.addService("http", "tcp", 80);
     ip_flag = 1;
   }

   void loop() {
     //Serial.println(WiFi.softAPgetStationNum()); //打印客户端连接数
     if(ip_flag == 1)
     {
       for(int i=3; i>0; i--)
       {
         Serial.print("IP: ");
         Serial.print(WiFi.localIP());
         Serial.println('#');
         delay(500);
       }
       ip_flag = 0;
       
     }
       MDNS.update();
       WiFiClient client = server.available();
       if (!client) {
         return;
       }
       //Serial.println("");
       while (client.connected() && !client.available()) {
         delay(1);
       }
       String req = client.readStringUntil('\r');
       int addr_start = req.indexOf(' ');
       int addr_end = req.indexOf(' ', addr_start + 1);
       if (addr_start == -1 || addr_end == -1) {
         //Serial.print("Invalid request: ");
         //Serial.println(req);
         return;
       }
       req = req.substring(addr_start + 1, addr_end);
       int len_val = String(req).length();
       String M_req = String(req).substring(0,6);
       //Serial.println(M_req);
       if(M_req == "/btn/u")
       {
         String s_M_req = String(req).substring(5,len_val);
         Serial.print(s_M_req);
         Serial.print("#");
       }
       if(M_req == "/btn/v")
       {
         String s_M_req = String(req).substring(5,len_val);
         Serial.print(s_M_req);
         Serial.print("#");
       }
       client.flush();
       String s;
       if (req == "/") {
         IPAddress ip = WiFi.localIP();
         String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
         s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
         s += ipStr;
         s += "</html>\r\n\r\n";
         //Serial.println("Sending 200");
         Serial.println(WiFi.localIP());
         Serial.write('*');
         client.println(WiFi.localIP());
         ip_flag = 0;
       }
       else if(req == "/btn/F")
       {
         Serial.write('F');
         client.println(F("F"));
       }
       else if(req == "/btn/B")
       {
         Serial.write('B');
         client.println(F("B"));
       }
       else if(req == "/btn/L")
       {
         Serial.write('L');
         client.println(F("L"));
       }
       else if(req == "/btn/R")
       {
         Serial.write('R');
         client.println(F("R"));
       }
       else if(req == "/btn/S")
       {
         Serial.write('S');
         client.println(F("S"));
       }
       else if(req == "/btn/a")
       {
         Serial.write('a');
         client.println(F("a"));
       }
       else if(req == "/btn/b")
       {
         Serial.write('b');
         client.println(F("b"));
       }
       else if(req == "/btn/c")
       {
         Serial.write('c');
         client.println(F("c"));
       }
       else if(req == "/btn/d")
       {
         Serial.write('d');
         client.println(F("d"));
       }
       else if(req == "/btn/e")
       {
         Serial.write('e');
         client.println(F("e"));
       }
       else if(req == "/btn/f")
       {
         Serial.write('f');
         client.println(F("f"));
       }
       else if(req == "/btn/g")
       {
         Serial.write('g');
         client.println(F("g"));
       }
       else if(req == "/btn/z")
       {
         Serial.write('z');
         client.println(F("z"));
       }
       else if(req == "/btn/i")
       {
         Serial.write('i');
         client.println(F("i"));
       }
       else if(req == "/btn/j")
       {
         Serial.write('j');
         client.println(F("j"));
       }
       else if(req == "/btn/k")
       {
         Serial.write('k');
         client.println(F("k"));
       }
       else if(req == "/btn/y")
       {
         Serial.write('y');
         client.println(F("y"));
       }
       else if(req == "/btn/l")
       {
         Serial.write('l');
         client.println(F("l"));
       }
       else if(req == "/btn/m")
       {
         Serial.write('m');
         client.println(F("m"));
       }
       else if(req == "/btn/n")
       {
         Serial.write('n');
         client.println("n");
       }
       else if(req == "/btn/o")
       {
         Serial.write('o');
         client.println(F("o"));
       }
       else if(req == "/btn/p")
       {
         Serial.write('p');
         client.println(F("p"));
       }
       else if(req == "/btn/q")
       {
         Serial.write('q');
         client.println("q");
       }
       else if(req == "/btn/x")
       {
         Serial.write('x');
         client.println(F("x"));
       }
       else if(req == "/btn/1")
       {
         Serial.write('1');
         client.println(F("1"));
       }
       else if(req == "/btn/2")
       {
         Serial.write('2');
         client.println("2");
       }
       else if(req == "/btn/3")
       {
         Serial.write('3');
         client.println(F("3"));
       }
       else if(req == "/btn/4")
       {
         Serial.write('4');
         client.println("4");
       }
       else if(req == "/btn/5")
       {
         Serial.write('5');
         client.println(F("5"));
       }
       else if(req == "/btn/0")
       {
         Serial.write('0');
         client.println("0");
       }
       else {
         //s = "HTTP/1.1 404 Not Found\r\n\r\n";
         //Serial.println("Sending 404");
       }

       client.print(F("IP : "));
       client.println(WiFi.localIP());
   }
   //**********************************************************************************

Wifi名称和Wifi密码修改后，确保USB转ESP-01S
WIFI模块串口测试扩展板上的拨码开关已经拨到Uart Download
端，并且也确定USB转ESP-01S
WIFI模块串口测试扩展板已经插入电脑的USB口。然后按照 **Arduino 教程中的
Project 16**
中的方法设置板型和COM口，IDE右下角显示对应板型和COM口，再点击\ |image121|\ 将ESP8266
代码上传到ESP8266串口WIFI
ESP-01模块上，上传成功。（注意：如果上传失败，在板型和COM口没问题情况下，将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来再次插到电脑的USB口)

ESP8266 代码上传成功后，先将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来，再将ESP8266串口WIFI
ESP-01模块从USB转ESP-01S WIFI模块串口测试扩展板上拔下来。

**Arduino Nano 实验代码**

|image122|

**注意：**
打开IDE后，一定要先设置好板型和COM口。如果家里没有WIFI需要打开手机热点共享WIFI。

.. code:: c++

   #include <Servo.h>
   Servo lgservo;
   #define ML 4
   #define ML_PWM 6
   #define MR 2
   #define MR_PWM 5
   #define servo2 A0

   char val;
   char wifiData;
   boolean servo_flag = 1;

   void setup() {
     Serial.begin(9600);
     pinMode(ML, OUTPUT);
     pinMode(ML_PWM, OUTPUT);
     pinMode(MR, OUTPUT);
     pinMode(MR_PWM, OUTPUT);
     
     lgservo.attach(A0);
     lgservo.write(0);
   }

   void loop() {
     if(Serial.available() > 0)
     {
       val = Serial.read();
       Serial.print(val);
     }
     switch(val)
     {
       case 'F': car_forward(); break;
       case 'B': car_back(); break;
       case 'L': car_left(); break;
       case 'R': car_right(); break;
       case 'S': car_stop(); break;
       case 'p': lgservo.write(55);servo_flag = 1; break;
       case 'x': servo_down(); break;
     }
   }

   void servo_down()
   {
     while( servo_flag == 1)
     {
       for(int i=55; i>0; i--)
       {
         lgservo.write(i);
         delay(2);
       }
       servo_flag = 0;
     }
     
   }


   void car_forward()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,255);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,255);
   }

   void car_back()
   {
     digitalWrite(ML,HIGH);
     analogWrite(ML_PWM,0);
     digitalWrite(MR,HIGH);
     analogWrite(MR_PWM,0);
   }

   void car_left()
   {
     digitalWrite(ML,HIGH);
     analogWrite(ML_PWM,150);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,105);
   }

   void car_right()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,105);
     digitalWrite(MR,HIGH);
     analogWrite(MR_PWM,150);
   }

   void car_stop()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,0);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,0);
   }

--------------

.. _24-kidsblockscratch代码:

2.4. KidsBlock(Scratch)代码:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**ESP8266 代码：**

|image123|

**注意：** 如果家里没有WIFI，需要打开手机热点共享WIFI.

|image-20230703132208975|

**特别注意：** 需要将ESP8266代码\ |image124|

中的Wifi名称和Wifi密码改成你们自己的Wifi名称和Wifi密码。

A. Wifi名称和Wifi密码修改后，确保USB转ESP-01S
WIFI模块串口测试扩展板上的拨码开关已经拨到Uart Download
端，并且也确定USB转ESP-01S
WIFI模块串口测试扩展板已经插入电脑的USB口，然后点击kidsblock软件上的“\ **上传**\ ”
按钮 。将ESP8266代码上传到ESP8266串口WIFI
ESP-01模块上，上传成功。（注意：如果上传失败，在板型和COM口没问题下，将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来再次插到电脑的USB口）

|image125|

B. ESP8266代码上传成功后，先将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来，再将ESP8266串口WIFI
ESP-01模块从USB转ESP-01S WIFI模块串口测试扩展板上拔下来。

**USB线连接电脑和Arduino Nano主板：**

|image126|

**Beetlebot页面设置:**

更换开发板，点击\ |image-20230703133342925|\ 进入设备选择页面，点击
“\ **套件**\ ”，选中 **Beetlebot 3in1 Robot for Arduino** ，单击“连接”。

|image-20230703133422037|

|image127|

|image-20230703133451215|

**Arduino Nano实验代码：**

|image128|

|image129|

.. _25-实验场景:

2.5. 实验场景
~~~~~~~~~~~~~

1.
在场地用乐高积木搭建几个目标物（目标物A，B，C，D，E），目标物在投石攻城车前方且都隔一段距离。APP连上WiFi。

2.
操作小车方向按钮\ |image130|\ 使投石攻城车正对目标物A一段距离，按住按钮\ |image131|\ ，舵机转动一定角度带动齿轮升起长臂把乐高积木块抛出去；松开按钮\ |image132|\ ，舵机转动带动齿轮把长臂向后推。看看乐高积木块是否打击到目标物A？如果没有，就反复操作小车方向按钮\ |image133|\ 、按住或松开按钮\ |image134|\ ，调整投石攻城车与目标物A之间的距离，使抛出去的乐高积木块刚好可以打击到目标物A。

3.
打击目标物B，C，D，E的操作方法和上面的一样。按住按钮\ |image135|\ ，舵机转动一定角度带动齿轮升起长臂把乐高积木块抛出去。

.. _3-搬运机器人:

3. 搬运机器人
-------------

.. _31-实验简介:

3.1. 实验简介
~~~~~~~~~~~~~

在众多的工业机器人中，搬运机器人无疑是应用率较高的机器人之一，不管是在工业制造、仓储物流、烟草、医药、食品、化工等行业领域，还是在邮局、图书馆、港口码头、机场、停车场等场景，都可以见到搬运机器人的身影。在本实验中，我们也利用乐高积木搭建了一款搬运机器人来搬运东西。

.. _32-搬运机器人形态安装步骤:

3.2. 搬运机器人形态安装步骤
~~~~~~~~~~~~~~~~~~~~~~~~~~~

将超声波云台拆下

|image136|

--------------

安装所需零件

|image137|

--------------

安装

|image138|

--------------

完成

|image139|

--------------

安装所需零件

|image140|

--------------

安装

|image141|

--------------

完成

|image142|

--------------

安装所需零件

|image143|

--------------

安装

|image144|

--------------

完成

|image145|

--------------

安装所需零件

|image146|

--------------

安装

|image147|

--------------

完成

|image148|

--------------

安装所需零件

|image149|

--------------

安装

|image150|

--------------

完成

|image151|

--------------

安装所需零件

|image152|

--------------

安装

|image153|

--------------

完成

|image154|

--------------

安装所需零件

|image155|

--------------

安装

|image156|

--------------

完成

|image157|

--------------

安装所需零件

|image158|

--------------

安装

|image159|

--------------

完成

|image160|

--------------

安装所需零件

|image161|

--------------

安装前需调节舵机角度为180°

将舵机的线接到PCB上板的S2接口，如下表:

====== =========
舵机   小车PCB板
====== =========
棕线   G
红线   5V
橙黄线 S2（A0）
====== =========

**Arduino代码：**

.. code:: c++

   #include <Servo.h>
   Servo myservo;  // create servo object to control a servo

   void setup() {
     myservo.attach(A0);  // attaches the servo on pin A0 to the servo object
     myservo.write(0);  // tell servo to go to position
     delay(1000);
     myservo.write(90);  // tell servo to go to position
     delay(1000);
     myservo.write(180);  // tell servo to go to position
     delay(1000);
   }

   void loop() {
     
   }

上面的Arduino代码在资料中有提供，打开舵机的调整代码并烧录到Beetlebot的主板，完成。代码如下图位置：

|image162|

**KidsBlock(Scratch)代码:**

也可以使用下面的Scratch-KidsBlock代码来调整舵机初始化角度.

|image163|

KidsBlock(Scratch)代码在资料中也有提供，打开舵机的调整代码并烧录到Beetlebot的主板，完成。代码如下图位置:

|image164|

--------------

安装（安装姿势与右图一致）

|image165|

--------------

完成

|image166|

--------------

安装所需零件

|image167|

--------------

安装

|image168|

--------------

安装

|image169|

--------------

完成

|image170|

--------------

完成

|image171|

--------------

完成

|image172|

--------------

舵机接线图

舵机接到板子上的S2接口

|image173|

.. _33-arduino代码:

3.3. Arduino代码
~~~~~~~~~~~~~~~~

**ESP8266代码：**

|image174|

**特别注意：** 需要先将项目代码

|image175|\ 中的用户Wifi名称和用户Wifi密码改成你们自己的Wifi名称和Wifi密码。

ESP8266串口WIFI ESP-01模块的UTXD引脚是由Arduino
Nano主板的IO口RX（0）控制，URXD引脚是由Arduino
Nano主板的IO口TX（1）控制。

.. code:: c++

   //**********************************************************************************
   /*
   ESP8266_Code
   */
   // generated by KidsBlock
   #include <Arduino.h>
   #include <ESP8266WiFi.h>
   #include <ESP8266mDNS.h>
   #include <WiFiClient.h>
   //#include <WiFi.h>

   #ifndef STASSID
   #define STASSID "ChinaNet-2.4G-0DF0"  //the name of user's Wifi
   #define STAPSK  "ChinaNet@233"       //the password of the user's wifi
   #endif
   const char* ssid = STASSID;
   const char* password = STAPSK;

   //IPAddress local_IP(192,168,4,22);
   //IPAddress gateway(192,168,4,22);
   //IPAddress subnet(255,255,255,0);
   //
   //const char *ssid = "ESP8266_AP_TEST";
   //const char *password = "12345678";

   WiFiServer server(80);
   String unoData = "";
   int ip_flag = 0;
   int ultra_state = 1;
   String ip_str;


   void setup() {
     Serial.begin(9600); 
   //   WiFi.mode(WIFI_AP); //设置工作在AP模式
   //
   //  WiFi.softAPConfig(local_IP, gateway, subnet); //设置AP地址
   //  while(!WiFi.softAP(ssid, password)){}; //启动AP
   //  Serial.println("AP启动成功");
   //
   //  Serial.print("IP address: ");
   //  Serial.println(WiFi.softAPIP()); // 打印IP地址
   //
   //  WiFi.softAPsetHostname("myHostName"); //设置主机名
   //  Serial.print("HostName: ");
   //  Serial.println(WiFi.softAPgetHostname()); //打印主机名
   //
   //  Serial.print("mac Address: ");
   //  Serial.println(WiFi.softAPmacAddress()); //打印mac地址

     WiFi.mode(WIFI_STA);
     WiFi.begin(ssid, password);
     while (WiFi.status() != WL_CONNECTED) {
       delay(500);
       Serial.print(".");
     }
     Serial.print("IP ADDRESS: ");
     Serial.println(WiFi.localIP());
     if (!MDNS.begin("esp8266")) {
       //Serial.println("Error setting up MDNS responder!");
       while (1) {
         delay(1000);
       }
     }
    // Serial.println("mDNS responder started");
     server.begin();
     //Serial.println("TCP server started");
     MDNS.addService("http", "tcp", 80);
     ip_flag = 1;
   }

   void loop() {
     //Serial.println(WiFi.softAPgetStationNum()); //打印客户端连接数
     if(ip_flag == 1)
     {
       for(int i=3; i>0; i--)
       {
         Serial.print("IP: ");
         Serial.print(WiFi.localIP());
         Serial.println('#');
         delay(500);
       }
       ip_flag = 0;
       
     }
       MDNS.update();
       WiFiClient client = server.available();
       if (!client) {
         return;
       }
       //Serial.println("");
       while (client.connected() && !client.available()) {
         delay(1);
       }
       String req = client.readStringUntil('\r');
       int addr_start = req.indexOf(' ');
       int addr_end = req.indexOf(' ', addr_start + 1);
       if (addr_start == -1 || addr_end == -1) {
         //Serial.print("Invalid request: ");
         //Serial.println(req);
         return;
       }
       req = req.substring(addr_start + 1, addr_end);
       int len_val = String(req).length();
       String M_req = String(req).substring(0,6);
       //Serial.println(M_req);
       if(M_req == "/btn/u")
       {
         String s_M_req = String(req).substring(5,len_val);
         Serial.print(s_M_req);
         Serial.print("#");
       }
       if(M_req == "/btn/v")
       {
         String s_M_req = String(req).substring(5,len_val);
         Serial.print(s_M_req);
         Serial.print("#");
       }
       client.flush();
       String s;
       if (req == "/") {
         IPAddress ip = WiFi.localIP();
         String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
         s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
         s += ipStr;
         s += "</html>\r\n\r\n";
         //Serial.println("Sending 200");
         Serial.println(WiFi.localIP());
         Serial.write('*');
         client.println(WiFi.localIP());
         ip_flag = 0;
       }
       else if(req == "/btn/F")
       {
         Serial.write('F');
         client.println(F("F"));
       }
       else if(req == "/btn/B")
       {
         Serial.write('B');
         client.println(F("B"));
       }
       else if(req == "/btn/L")
       {
         Serial.write('L');
         client.println(F("L"));
       }
       else if(req == "/btn/R")
       {
         Serial.write('R');
         client.println(F("R"));
       }
       else if(req == "/btn/S")
       {
         Serial.write('S');
         client.println(F("S"));
       }
       else if(req == "/btn/a")
       {
         Serial.write('a');
         client.println(F("a"));
       }
       else if(req == "/btn/b")
       {
         Serial.write('b');
         client.println(F("b"));
       }
       else if(req == "/btn/c")
       {
         Serial.write('c');
         client.println(F("c"));
       }
       else if(req == "/btn/d")
       {
         Serial.write('d');
         client.println(F("d"));
       }
       else if(req == "/btn/e")
       {
         Serial.write('e');
         client.println(F("e"));
       }
       else if(req == "/btn/f")
       {
         Serial.write('f');
         client.println(F("f"));
       }
       else if(req == "/btn/g")
       {
         Serial.write('g');
         client.println(F("g"));
       }
       else if(req == "/btn/z")
       {
         Serial.write('z');
         client.println(F("z"));
       }
       else if(req == "/btn/i")
       {
         Serial.write('i');
         client.println(F("i"));
       }
       else if(req == "/btn/j")
       {
         Serial.write('j');
         client.println(F("j"));
       }
       else if(req == "/btn/k")
       {
         Serial.write('k');
         client.println(F("k"));
       }
       else if(req == "/btn/y")
       {
         Serial.write('y');
         client.println(F("y"));
       }
       else if(req == "/btn/l")
       {
         Serial.write('l');
         client.println(F("l"));
       }
       else if(req == "/btn/m")
       {
         Serial.write('m');
         client.println(F("m"));
       }
       else if(req == "/btn/n")
       {
         Serial.write('n');
         client.println("n");
       }
       else if(req == "/btn/o")
       {
         Serial.write('o');
         client.println(F("o"));
       }
       else if(req == "/btn/p")
       {
         Serial.write('p');
         client.println(F("p"));
       }
       else if(req == "/btn/q")
       {
         Serial.write('q');
         client.println("q");
       }
       else if(req == "/btn/x")
       {
         Serial.write('x');
         client.println(F("x"));
       }
       else if(req == "/btn/1")
       {
         Serial.write('1');
         client.println(F("1"));
       }
       else if(req == "/btn/2")
       {
         Serial.write('2');
         client.println("2");
       }
       else if(req == "/btn/3")
       {
         Serial.write('3');
         client.println(F("3"));
       }
       else if(req == "/btn/4")
       {
         Serial.write('4');
         client.println("4");
       }
       else if(req == "/btn/5")
       {
         Serial.write('5');
         client.println(F("5"));
       }
       else if(req == "/btn/0")
       {
         Serial.write('0');
         client.println("0");
       }
       else {
         //s = "HTTP/1.1 404 Not Found\r\n\r\n";
         //Serial.println("Sending 404");
       }

       client.print(F("IP : "));
       client.println(WiFi.localIP());
   }
   //**********************************************************************************

Wifi名称和Wifi密码修改后，确保USB转ESP-01S
WIFI模块串口测试扩展板上的拨码开关已经拨到Uart Download
端，并且也确定USB转ESP-01S
WIFI模块串口测试扩展板已经插入电脑的USB口。然后按照 **Arduino 教程中的
Project 16**
中的方法设置板型和COM口，IDE右下角显示对应板型和COM口，再点击\ |image176|\ 将ESP8266
代码上传到ESP8266串口WIFI
ESP-01模块上，上传成功。（注意：如果上传失败，在板型和COM口没问题情况下，将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来再次插到电脑的USB口)

ESP8266 代码上传成功后，先将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来，再将ESP8266串口WIFI
ESP-01模块从USB转ESP-01S WIFI模块串口测试扩展板上拔下来。

**Arduino Nano 实验代码**

|image177|

**注意：**
打开IDE后，一定要先设置好板型和COM口。如果家里没有WIFI需要打开手机热点共享WIFI。

.. code:: c++

   #include <Servo.h>
   Servo lgservo;
   #define ML 4
   #define ML_PWM 6
   #define MR 2
   #define MR_PWM 5
   #define servo2 A0

   char val;
   char wifiData;

   void setup() {
     Serial.begin(9600);
     pinMode(ML, OUTPUT);
     pinMode(ML_PWM, OUTPUT);
     pinMode(MR, OUTPUT);
     pinMode(MR_PWM, OUTPUT);
     
     lgservo.attach(A0);
     lgservo.write(180);
   }

   void loop() {
     if(Serial.available() > 0)
     {
       val = Serial.read();
       Serial.print(val);
     }
     switch(val)
     {
       case 'F': car_forward(); break;
       case 'B': car_back(); break;
       case 'L': car_left(); break;
       case 'R': car_right(); break;
       case 'S': car_stop(); break;
       case 'p': lgservo.write(130); break;
       case 'x': lgservo.write(180); break;
     }
   }


   void car_forward()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,127);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,127);
   }

   void car_back()
   {
     digitalWrite(ML,HIGH);
     analogWrite(ML_PWM,127);
     digitalWrite(MR,HIGH);
     analogWrite(MR_PWM,127);
   }

   void car_left()
   {
     digitalWrite(ML,HIGH);
     analogWrite(ML_PWM,150);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,105);
   }

   void car_right()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,105);
     digitalWrite(MR,HIGH);
     analogWrite(MR_PWM,150);
   }

   void car_stop()
   {
     digitalWrite(ML,LOW);
     analogWrite(ML_PWM,0);
     digitalWrite(MR,LOW);
     analogWrite(MR_PWM,0);
   }

--------------

.. _34-kidsblockscratch代码:

3.4. KidsBlock(Scratch)代码:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**ESP8266 代码：**

|image178|

**注意：** 如果家里没有WIFI，需要打开手机热点共享WIFI.

|image-20230703132208975|

**特别注意：** 需要将ESP8266代码\ |image179|

中的Wifi名称和Wifi密码改成你们自己的Wifi名称和Wifi密码。

A. Wifi名称和Wifi密码修改后，确保USB转ESP-01S
WIFI模块串口测试扩展板上的拨码开关已经拨到Uart Download
端，并且也确定USB转ESP-01S
WIFI模块串口测试扩展板已经插入电脑的USB口，然后点击kidsblock软件上的“\ **上传**\ ”
按钮 。将ESP8266代码上传到ESP8266串口WIFI
ESP-01模块上，上传成功。（注意：如果上传失败，在板型和COM口没问题下，将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来再次插到电脑的USB口）

|image180|

B. ESP8266代码上传成功后，先将USB转ESP-01S
WIFI模块串口测试扩展板从电脑的USB口拔下来，再将ESP8266串口WIFI
ESP-01模块从USB转ESP-01S WIFI模块串口测试扩展板上拔下来。

**USB线连接电脑和Arduino Nano主板：**

|image181|

|image182|

--------------

.. _35-实验场景:

3.5. 实验场景
~~~~~~~~~~~~~

1.
在投石攻城车项目实验中，投石攻城车抛乐高积木块击打目标物A、B、C、D散落满地的一些乐高积木。
2.
APP连上WiFi，操作小车方向按钮\ |image183|\ 使搬运机器人移动到散落满地的乐高积木旁。

3.
用手拣一些小的乐高积木块放到铲斗上，操作小车方向按钮\ |image184|\ 使搬运机器人把乐高积木搬运到原始位置。按住按钮\ |image185|\ ，舵机转动一定角度带动齿轮使铲斗升起，这样，运送的乐高积木块就掉下来。

4. 重复上面的操作方法，把所有的乐高积木块都搬运到原始位置。

.. |img| image:: ./img/5e64e86f88135f370916439bbabb2d5a.png
.. |image1| image:: ./img/52bddcd05b409305adfbb39a9af55ee6.png
.. |image2| image:: ./img/9b295f5c6b71340264eb54fd701296d6.png
.. |image3| image:: ./img/448e4708895f49afd985391c8ac0cd04.png
.. |image4| image:: ./img/b7ca00b9d07fc08780f5e6e39595d974.png
.. |image5| image:: ./img/d124cb9095a9cecb1eea4c9b565da3dd.png
.. |image6| image:: ./img/ef1331144242e5bc24bc426842d98573.png
.. |image7| image:: ./img/2520ee435d034c60b66058e4bacfadb6.png
.. |image8| image:: ./img/1d88fd0c5f6b4aff89c3900b3df5533d.png
.. |image9| image:: ./img/d05ab09c6662e3fb4d62be4f355a91be.png
.. |image10| image:: ./img/82c5dd6fbe0818dbdbaf33ee0b019215.png
.. |image11| image:: ./img/5964ab1fd800a0522923960dd32be299.png
.. |image12| image:: ./img/29abea2f58433515043942fd37af34e7.png
.. |image13| image:: ./img/cbd663b428c32fe4630a72a288375f16.png
.. |image14| image:: ./img/a643659079fdbf1433bb40658a590675.png
.. |image15| image:: ./img/9ec78ee08c51b297ccaa34b13fa8ae8d.png
.. |image16| image:: ./img/d3ae331c69d05147a98b9d8353496a9f.png
.. |image17| image:: ./img/77092cee1e554dc3b259b2a1ef7f6e4e.png
.. |image18| image:: ./img/f939d187c78455662d9c3fd3bc77d8b7.png
.. |image19| image:: ./img/f2a0fea032c9ca807196bae481054b82.png
.. |image20| image:: ./img/e9fb139ce5954ee5d0cc32028b15d1a4.png
.. |image21| image:: ./img/dc849d125d6cf7748725d369ca39b6f2.png
.. |image22| image:: ./img/a5a63691438159b9a73716e175053183.png
.. |image23| image:: ./img/d65a5580f2fc3292ad22005e1b480a3c.png
.. |image24| image:: ./img/54d2787ec549a6d651753475ca760f6b.png
.. |image25| image:: ./img/f410d612e4ea08f789b5f8c2fe625947.png
.. |image26| image:: ./img/44cdf3a043fe3e1e7c8dd46213dbe5c9.png
.. |image27| image:: ./img/9395f136b5fea019576ae3e4616467d7.png
.. |image28| image:: ./img/713bc86a9b595ead63a0f4cb48db2682.png
.. |image29| image:: ./img/6ca744b12dab6f6cc97459d6ae482f12.png
.. |image30| image:: ./img/8af91d1c4c7cb21ec247d18e8783389e.png
.. |image31| image:: ./img/2a9fe97a9d824c86bf60331578ff299a.png
.. |image32| image:: ./img/228346c56280be9b2516abd39c9fa7c7.png
.. |image33| image:: ./img/3b9a3a2fce95bcf48fc833aed69fe4b6.png
.. |image34| image:: ./img/4864d2e95de4370bf52cc922d4c38191.png
.. |image35| image:: ./img/31805e285ab9d3c8b487fe769c97574b.png
.. |image36| image:: ./img/4a59747ea4ecc8e8eb328935007684b4.png
.. |image37| image:: ./img/40ced3c517b76bdca41bb867388291cc.png
.. |image38| image:: ./img/78fc2bcd7bcb4df80bb2377087a730a3.png
.. |image39| image:: img/0fc16ff134aa3503319d4101362338d8.png
.. |image40| image:: img/1bd86df44aba070fea465a1da26df9e9.png
.. |image41| image:: img/f3749804b3ac033cfdd7b4423ddea660.png
.. |image42| image:: img/8d3f4c81812931c8cb3140c5fc33aa1a.png
.. |image43| image:: img/dcc81f3f50258615595745676921b34c.png
.. |image44| image:: img/567e873c86303e9e7ef0f6c919ae8fac.png
.. |image45| image:: img/99d485c0ce81fe195bd9d4282403b8f1.png
.. |image46| image:: img/5d749f5431468ffc7be947dfafd68223.png
.. |image47| image:: img/q9.png
.. |Img| image:: ./media/img-20250507142534.png
.. |image48| image:: ./img/b7c05c445dd30cf5ec743fb09bfec1fc.jpg
.. |image49| image:: ./img/wps71.jpg
.. |image50| image:: ./media/img-20250507144338.png
.. |image51| image:: ./media/img-20250507144454.png
.. |image-20230703132208975| image:: ./img/image-20230703132208975.png
.. |image52| image:: ./img/wps46-1688350484235-17.jpg
.. |image53| image:: ./img/wps47-1688350484236-18.jpg
.. |image54| image:: ./img/wps48-1688350484236-19.jpg
.. |image-20230703133342925| image:: ./img/image-20230703133342925.png
.. |image-20230703133422037| image:: ./img/image-20230703133422037.png
.. |image55| image:: ./img/wps58.png
.. |image-20230703133451215| image:: ./img/image-20230703133451215.png
.. |image56| image:: ./media/img-20250507144632.png
.. |image57| image:: ./media/img-20250507143727.png
.. |image58| image:: img/3.png
.. |image59| image:: img/4.png
.. |image60| image:: img/c6d6fb5f7473c0aabcdeddb580b740ed.png
.. |image61| image:: img/8e7f403444f5a5b8c5030000918e9b5d.png
.. |image62| image:: img/6f7ef5ee652735559a5bb37a0e5a7057.png
.. |image63| image:: img/5524822fee3e578da64fa98323a02c91.png
.. |image64| image:: img/af71c68c2096d0b9be62f8f1b90f5788.png
.. |image65| image:: img/cfc67549b45fdc99b20a5af6dead6dfd.png
.. |image66| image:: img/7a0786249dbabc401b3d3c144ba27f96.png
.. |image67| image:: img/b56a8756d9c485559111af2d3b7a1535.png
.. |image68| image:: img/884d0594a94508c143794ae4f93e3031.png
.. |image69| image:: img/1a1cbc3a9a330d17171c0367e6cf7926.png
.. |image70| image:: img/7cece542705c56e9f1069989882a59d1.png
.. |image71| image:: img/e4bf7576a162959e6177e13aaf3dbda8.png
.. |image72| image:: img/52ec48634381303e4c2d7c6e21b12e10.png
.. |image73| image:: img/87aba8f9d7da40c98584c29b35730fff.png
.. |image74| image:: img/076e6d8c2645691b836a9cc8a2a267ab.png
.. |image75| image:: img/5779b7073f69eb4ed951411f632ca289.png
.. |image76| image:: img/5c09abb8e5652965cfbbc1cf1c1f1074.png
.. |image77| image:: img/dd6f5fb79caca05bb0737c50d21d9c71.png
.. |image78| image:: img/35fdb3fbae47f7b7bf36176eae68c05b.png
.. |image79| image:: img/7b8db88df9ea2672a28377cf6bc3d840.png
.. |image80| image:: img/23e700b90f41ae523999a0ce43e18869.png
.. |image81| image:: img/0d6a86d4dd911468a5ad23acb41af362.png
.. |image82| image:: img/7b694c4fd729cfc214eba81022145158.png
.. |image83| image:: img/67f7ee61f5908e636aa53290c491af3d.png
.. |image84| image:: img/560d08dce32498417d0a4a1aa3d42adf.png
.. |image85| image:: img/15e969bc6435c7ca54d1e982bd259e7d.png
.. |image86| image:: img/fbc1562f6195d23013d3cbaa4b34bb24.png
.. |image87| image:: img/84491cc6b92d6adccc0b937039aacc68.png
.. |image88| image:: img/d851de0a2e985ec8b2693b8ecf815f4c.png
.. |image89| image:: img/02ca4fae73f19ad00a21fd452e85d7ff.png
.. |image90| image:: img/34f945ba2cf2570556a2aa774b89cc8e.png
.. |image91| image:: img/9abd5fa35e3907101c35a0d050bea4c8.png
.. |image92| image:: img/2d05e0c9c6dee04c7783b266ed602074.png
.. |image93| image:: img/742d5958f788815258e1d8363d1abb54.png
.. |image94| image:: img/2dd49108426c570b7d2fdf8a01731d9b.png
.. |image95| image:: img/53ea3da7a72a4eaafd0cb408171a0ec6.png
.. |image96| image:: img/2ba6ba28ff8acf59a3c82aa4080c2b12.png
.. |image97| image:: img/093337079c3f016e15efbacce031474b.png
.. |image98| image:: img/4b55683a9b6da05c2e400242cc2f80a3.png
.. |image99| image:: img/851600cb9154b24a70f5872848e7a97e.png
.. |image100| image:: img/3968ec24615925d922c0a5edd22ac3ce.png
.. |image101| image:: img/8c0f13d7ee6013d273b0c7cf3f81189c.png
.. |image102| image:: img/e448a8422fcd6e17fc03f5fe5b330491.png
.. |image103| image:: img/47cff6eaca708b08475427ab5fe59e0e.png
.. |image104| image:: img/cadc2981d990c0c3a0616a7975b7907a.png
.. |image105| image:: img/5ce1bd3e98b3e3981e4715ce9c40746e.png
.. |image106| image:: img/0d214bb823a8f9c3e77d67bf4f8df0fd.png
.. |image107| image:: img/d5e1244f2825a1b85772e414f4a434d8.png
.. |image108| image:: img/ff3e1fb83e913733c891fbde85051440.png
.. |image109| image:: img/3863720b2935be7965184d434a32a3b8.png
.. |image110| image:: img/c05bbcc57b7f3e8c1410c5a3d8f3fde8.png
.. |image111| image:: img/cbf249b15ba20b99cd1aa73a247b06fb.png
.. |image112| image:: img/4a8430468e88882e2c15238a926f4931.png
.. |image113| image:: img/68b29a156f020798ff4205123aa548ed.png
.. |image114| image:: img/3bfb5fd29681617f140d8f67c2c991c8.png
.. |image115| image:: img/f263b85fc91e8c7b35a6bc593416084e.png
.. |image116| image:: img/dce77bd674631f1b3f030db417fb67ea.png
.. |image117| image:: img/314d41aab13b7ef6e1a8dc9265065a32.png
.. |image118| image:: img/a6b5b27faa970fefb3a33c510a58bdd9.png
.. |image119| image:: ./media/img-20250507150944.png
.. |image120| image:: ./img/b7c05c445dd30cf5ec743fb09bfec1fc.jpg
.. |image121| image:: ./img/wps71.jpg
.. |image122| image:: img/d2e61e2b876eff4a39932125ebb02830.png
.. |image123| image:: ./media/img-20250507151057.png
.. |image124| image:: ./img/wps46-1688350484235-17.jpg
.. |image125| image:: ./img/wps47-1688350484236-18.jpg
.. |image126| image:: ./img/wps48-1688350484236-19.jpg
.. |image127| image:: ./img/wps58.png
.. |image128| image:: img/eca65ee22de62ded38eb566a4e2c52b3.png
.. |image129| image:: ./media/img-20250507155312.png
.. |image130| image:: img/1.png
.. |image131| image:: img/2.png
.. |image132| image:: img/3.png
.. |image133| image:: img/4.png
.. |image134| image:: img/0e62c323c0018af1a2824a120d447bda.png
.. |image135| image:: img/0e62c323c0018af1a2824a120d447bda.png
.. |image136| image:: img/f05a58fdd61093240a78a884d2484bab.png
.. |image137| image:: img/1f8438657adee5ee0931a2e0db8c8d79.png
.. |image138| image:: img/b9cb95a5c53ab96b85b41d648c19534f.png
.. |image139| image:: img/502348fe825fa6e57cd61d1700c93c0f.png
.. |image140| image:: img/ca7778dd2175c92f92c86611b9fc64d3.png
.. |image141| image:: img/d33b93e264a8c2833ce2b3d4dcd91517.png
.. |image142| image:: img/c9a151d3856720e100dabe436d62d230.png
.. |image143| image:: img/a2b2a96f444801e2da559161cc5b2b65.png
.. |image144| image:: img/077d7de8e6260998b60e008593bff7e5.png
.. |image145| image:: img/a9a493a264445b0feab48159837fe725.png
.. |image146| image:: img/4570e1fc0c6b67a1012291d22a4882a9.png
.. |image147| image:: img/0f804e35e2f7dc6e2a028d21f21e392e.png
.. |image148| image:: img/4a759b55f056a6cd9dfdee0cece5dfd1.png
.. |image149| image:: img/064acf2eab1416e7699f3478f1859536.png
.. |image150| image:: img/ce5e3e8e4548aba8fad60910214bcca6.png
.. |image151| image:: img/9b2185eaf2f66f35b57754d5476b1ddd.png
.. |image152| image:: img/ac98e23dc24258097c9738102ea3a43a.png
.. |image153| image:: img/7164d7dd08e97a62bc77ae08aadf1526.png
.. |image154| image:: img/1cccaf2a536170c11bbc4cdf7683484a.png
.. |image155| image:: img/7d3e50e74ae36545217c4fa15a53d04e.png
.. |image156| image:: img/7d32a51858167fd8aee486b72f287ae3.png
.. |image157| image:: img/83dbaa2175018608dc84f4dda726fa96.png
.. |image158| image:: img/6e73265906657a00ca17c5323f65dcec.png
.. |image159| image:: img/f60d276bb389be3c440b15adea292adf.png
.. |image160| image:: img/86f43f7d15cfb6c4ac807423b2510de0.png
.. |image161| image:: img/df4b2ab9b8ad767b948de6f783a0cf42.png
.. |image162| image:: img/9a13cc561e0afa36543424bf2d62700e.png
.. |image163| image:: img/4eedb544be915b095c80f7ba56e5abfa.png
.. |image164| image:: img/a640ff4cc0676fe4340fde2a4ca49b9b.png
.. |image165| image:: img/014d0f844d18f7bbd2a80b7f1679fca1.png
.. |image166| image:: img/e66813dd3c1884b0c1f65bdf3f5b8c48.png
.. |image167| image:: img/13c2436b53b5dab5f508e902bcb6b0cf.png
.. |image168| image:: img/20149b66db795ce32fcb060a0823bab0.png
.. |image169| image:: img/b97e180d74ce41e7293acfe85a0b1bd7.png
.. |image170| image:: img/b1d1dd5fe42bc14bbf773e9e10cdcab9.png
.. |image171| image:: img/87076fbdd533d91c88fa7ae5cd5df32e.png
.. |image172| image:: img/89d2a853cf95635fae60b5ec48482d54.png
.. |image173| image:: img/d21937e59f71e552c4deb19e1a91b6d3.png
.. |image174| image:: ./media/img-20250507151803.png
.. |image175| image:: ./img/b7c05c445dd30cf5ec743fb09bfec1fc.jpg
.. |image176| image:: ./img/wps71.jpg
.. |image177| image:: img/7de32e6ebd19cf26bd5f64b1dc14fce8.png
.. |image178| image:: ./media/img-20250507151911.png
.. |image179| image:: ./img/wps46-1688350484235-17.jpg
.. |image180| image:: ./img/wps47-1688350484236-18.jpg
.. |image181| image:: img/65a20680925315be7696996ceeca0afd.png
.. |image182| image:: ./media/img-20250507155328.png
.. |image183| image:: img/9156e9f56b1c2c405809be27453970ce.png
.. |image184| image:: img/9156e9f56b1c2c405809be27453970ce.png
.. |image185| image:: img/35465538ab0f0480ae9fe32e4b1f850c.png
