LEGO扩展教程#

1. 足球机器人#

1.1. 实验简介:#

足球运动是一种大家非常喜爱的运动。让 机器人去踢足球,听起来像天方夜谭似的。机器人也能去踢足球? 是的,足球机器人可以做到像我们人一样去组成团队进行踢足球比赛,比如:一年一度的RoboCup机器人世界杯—RoboCup足球赛等。在本实验中,我们利用乐高积木搭建了一款足球机器人,并且使用足球机器人把小足球送进足球门里。

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代码:

#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

1.3. 足球门安装步骤#

安装所需零件

image39


安装

image40


完成

image41


安装所需零件

image42


安装

image43


完成

image44


安装所需零件

image45


安装

image46


完成

image47


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)控制。

//**********************************************************************************
/*
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。

#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);
}

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


1.6. 实验场景:#

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

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

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

2. 投石攻城车#

2.1. 实验简介#

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

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代码:

#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

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)控制。

//**********************************************************************************
/*
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。

#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);
}

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

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.1. 实验简介#

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

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代码:

#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

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)控制。

//**********************************************************************************
/*
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。

#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);
}

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


3.5. 实验场景#

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

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

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